I am facing issue in navigating to URL. My default page set to Login and my application URL is http://localhost:12345/#/
.
This works well but there are two ways the user can login to application
- Direct through the application.
- Getting username and password trough query string.
When application is logging through Query String the url is like http://localhost:12345?auth=123654654656564/#/
.
I would like to remove auth value from the URL. I tried to map the routing but it doesn't work.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Account", action = "Login"}
);
And also i tried to create one more action result that will return the view
routes.MapRoute(
name: "ActualDefault",
url: "{controller}/{action}",
defaults: new { controller = "Account", action = "LoginQuery" }
);
Controller:
public ActionResult Login()
{
if (Request.QueryString.Count > 0 && Request.QueryString != null)
{
//validating
return RedirectToAction("LoginQuery", "Account");
}
else
{
return View();
}
}
public ActionResult LoginQuery()
{
return View("Index");
}
The above code removes query string but the URL will be http://localhost:12345/Account/LoginQuery/#/
.
I just need the URL like http://localhost:12345/#/
.
I would be negligent not to point out that this is an extremely bad practice. You should always use HTTP POST when logging into an application and send the user secrets in the body of the post, not the query string.
See
- Handling Form Edit and Post Scenarios
- Submit Form with Parameters in ASP.NET MVC
- BUILDING ASP.NET MVC FORMS WITH RAZOR
Note that you can also create forms in plain HTML (or via angularjs) to call an MVC action method, or you can make an HTTP POST via JavaScript or some other programming language to do the same thing.
Query string values are completely ignored by MVC routing. But you can make a custom route use query string values.
public class LoginViaQueryStringRoute : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var path = httpContext.Request.Path;
if (!string.IsNullOrEmpty(path))
{
// Don't handle URLs that have a path /controller/action
return null;
}
var queryString = httpContext.Request.QueryString;
if (!queryString.HasKeys())
{
// Don't handle the route if there is no query string.
return null;
}
if (!queryString.AllKeys.Contains("username") && !queryString.AllKeys.Contains("password"))
{
// Don't handle the case where controller and action are missing.
return null;
}
var routeData = new RouteData(this, new MvcRouteHandler());
routeData.Values["controller"] = "Account";
routeData.Values["action"] = "LoginQuery";
routeData.Values["username"] = queryString["username"];
routeData.Values["password"] = queryString["password"];
return routeData;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
return null;
}
}
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(new LoginViaQueryStringRoute());
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
This route will now match http://localhost:12345/?username=foo&password=bar
and send it to your LoginQuery
action method.
http://localhost:12345/#/
It is unclear how you expect this to work. Since everything after the hash tag are generally not sent to the server from the browser, http://localhost:12345/#/
is equivalent to http://localhost:12345/
. So, you are effectively saying "I want my home page to be the login page".
In a typical MVC application, you would setup an AuthorizeAttribute
on the home page to redirect the user to the login page. After the user logs in, they would be redirected back to the home page (or usually whatever secured page they initially requested).
[Authorize]
public ActionResult Index()
{
return View();
}
If you want all of your application secured, you can register the AuthorizeAttribute
globally and use AllowAnonymousAttribute
on your public action methods (such as the login and register pages).
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new AuthorizeAttribute());
filters.Add(new HandleErrorAttribute());
}
}
And your login action methods:
[AllowAnonymous]
public ActionResult Login()
{
//...
}
[AllowAnonymous]
[HttpPost]
public ActionResult Login(LoginModel model)
{
//...
}
[AllowAnonymous]
public ActionResult LoginQuery(string username, string password)
{
//...
}
But then, that is a typical MVC-only application.
If you are using Angular to make a SPA, then this could be a very different story. Namely, you would probably switch views on the client side without doing an HTTP 302 redirect to the login form (perhaps it would be a popup - who knows). The point is, without any details of how the client is setup to communicate with MVC, it is not possible to give you any useful advice on setting up MVC for your client beyond how you would typically setup MVC to work in a multi-page application.
NOTE: I can tell you that your routing is misconfigured. The
Default
andActualDefault
definitions cannot exist in the same route configuration because the first match always wins, therefore the first one will run and the other one will never run. Both of the route URL definitions will match any URL that is 0, 1, or 2 segments in length, so whichever you have first in the route table will match and the other one will be an unreachable execution path.