AngularJS 哈希 url 和 MVC 路由

AngularJS hash url and MVC routing

我在导航到 URL 时遇到问题。我的默认页面设置为登录,我的应用程序 URL 是 http://localhost:12345/#/.

这很好用,但用户可以通过两种方式登录应用程序

  1. Direct through the application.
  2. Getting username and password trough query string.

当应用程序通过查询字符串记录时,url 类似于 http://localhost:12345?auth=123654654656564/#/

我想从 URL 中删除 auth 值。我尝试映射路由但它不起作用。

routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}",
            defaults: new { controller = "Account", action = "Login"}
);

而且我还尝试再创建一个操作结果,它将 return view

routes.MapRoute(
            name: "ActualDefault",
            url: "{controller}/{action}",
            defaults: new { controller = "Account", action = "LoginQuery" }
);

控制器:

 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");
 }

上面的代码删除了查询字符串,但 URL 将是 http://localhost:12345/Account/LoginQuery/#/

我只需要像 http://localhost:12345/#/ 这样的 URL。

通过查询字符串登录

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

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.

查询字符串值被 MVC 路由 完全忽略。但是您可以使自定义路由使用查询字符串值。

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 }
        );
    }
}

此路由现在将匹配 http://localhost:12345/?username=foo&password=bar 并将其发送到您的 LoginQuery 操作方法。

通过http://localhost:12345/#/

登录

不清楚您希望它如何工作。由于 hash 标签后的所有内容一般不会从浏览器发送到服务器,因此 http://localhost:12345/#/ 等同于 http://localhost:12345/。所以,您实际上是在说“我希望我的主页成为登录页面”。

在典型的 MVC 应用程序中,您会在主页上设置 AuthorizeAttribute 将用户重定向 到登录页面。用户登录后,他们将被重定向回主页(或者通常是他们最初请求的任何安全页面)。

[Authorize]
public ActionResult Index()
{
    return View();
}

如果您希望 所有应用程序 安全,您可以全局注册 AuthorizeAttribute 并在 public 操作方法上使用 AllowAnonymousAttribute (例如登录和注册页面)。

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new AuthorizeAttribute());
        filters.Add(new HandleErrorAttribute());
    }
}

以及您的登录操作方法:

[AllowAnonymous]
public ActionResult Login()
{
    //...
}

[AllowAnonymous]
[HttpPost]
public ActionResult Login(LoginModel model)
{
    //...
}

[AllowAnonymous]
public ActionResult LoginQuery(string username, string password)
{
    //...
}

但是,这是典型的 MVC-only 应用程序。

如果您使用 Angular 制作 SPA,那么这可能是一个非常不同的故事。也就是说,您可能会在客户端 切换视图,而无需执行 HTTP 302 重定向 到登录表单(也许它会是一个弹出窗口 - 谁知道呢)。关键是,如果没有关于如何设置客户端与 MVC 通信的任何详细信息,除了通常如何设置 MVC 以在多页应用程序中工作之外,不可能为您提供有关为客户端设置 MVC 的任何有用建议.

NOTE: I can tell you that your routing is misconfigured. The Default and ActualDefault definitions cannot exist in the same route configuration , 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.