URL-адрес AngularJS и маршрутизация MVC

Я столкнулся с проблемой при переходе по URL. Моя страница по умолчанию настроена на Вход, а URL моего приложения http://localhost:12345/#/,

Это работает хорошо, но есть два способа, которыми пользователь может войти в приложение

  1. Прямо через приложение.
  2. Получение имени пользователя и пароля через строку запроса.

Когда приложение регистрируется через строку запроса, URL-адрес http://localhost:12345?auth=123654654656564/#/,

Я хотел бы удалить значение auth из URL. Я пытался отобразить маршрут, но он не работает.

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

А также я попытался создать еще один результат действия, который вернет 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/#/,

Мне просто нужен URL как http://localhost:12345/#/,

1 ответ

Решение

Вход через строку запроса

Я бы не стал указывать, что это крайне плохая практика. Вы всегда должны использовать HTTP POST при входе в приложение и отправлять секреты пользователя в теле сообщения, а не в строке запроса.

Увидеть

Обратите внимание, что вы также можете создавать формы в простом HTML (или через angularjs) для вызова метода действия MVC, или вы можете сделать HTTP POST через JavaScript или другой язык программирования, чтобы сделать то же самое.

Значения строки запроса полностью игнорируются маршрутизацией 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/#/

Неясно, как вы ожидаете, что это будет работать. Поскольку все после хеш-тега, как правило, не отправляются на сервер из браузера, http://localhost:12345/#/ эквивалентно http://localhost:12345/, Итак, вы фактически говорите: "Я хочу, чтобы моя домашняя страница была страницей входа".

В типичном приложении MVC вы должны настроить AuthorizeAttribute на домашней странице, чтобы перенаправить пользователя на страницу входа. После входа пользователя они будут перенаправлены обратно на домашнюю страницу (или, как правило, на любую защищенную страницу, которую они первоначально запрашивали).

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

Если вы хотите, чтобы все ваши заявки были защищены, вы можете зарегистрировать AuthorizeAttribute глобально и использовать 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- единственное приложение.

Если вы используете Angular для создания SPA, то это может быть совсем другая история. А именно, вы, вероятно, переключили бы представления на стороне клиента без перенаправления HTTP 302 в форму входа (возможно, это будет всплывающее окно - кто знает). Дело в том, что без каких-либо подробностей о том, как клиент настроен для взаимодействия с MVC, невозможно дать вам какой-либо полезный совет по настройке MVC для вашего клиента, помимо того, что вы обычно настраиваете MVC для работы в многостраничном приложении.,

ПРИМЕЧАНИЕ. Я могу вам сказать, что ваш маршрут неверно настроен. Default а также ActualDefault определения не могут существовать в одной и той же конфигурации маршрута, потому что первое совпадение всегда выигрывает, поэтому первое будет выполняться, а другое никогда не будет выполняться. Оба определения URL-адреса маршрута будут совпадать с любым URL-адресом длиной 0, 1 или 2 сегмента, поэтому в зависимости от того, что у вас будет первым в таблице маршрутов, будет совпадать, а другой будет недостижимым путем выполнения.

Другие вопросы по тегам