Подтвердить что ты не робот

ASP.NET 5 + Angular 2 маршрутизации (страница шаблона без загрузки)

Angular 2 beta использует html5 маршрутизацию по умолчанию. Однако при переходе к компоненту и изменению маршрута (например, http://localhost:5000/aboutus) и вы перезагружаете/обновляете страницу, ничего не происходит загружен.

Проблема была поднята в этом сообщении. Большинство ответов говорят о том, что если мы будем проводить маршрутизацию HTML5 в angular 2, то эту проблему маршрутизации следует заботиться на стороне сервера. Подробнее обсуждение здесь.

Я не уверен, как справиться с этой проблемой, используя среду сервера asp.net.

Любой angular 2 разработчик, который также использует asp.net и сталкивается с этой проблемой?

PS. Я использую ASP.NET 5. Мои маршруты angular 2 используют маршруты MVC.

4b9b3361

Ответ 1

Проблема, которую вы видите, связана с разницей между маршрутизацией Angular на стороне клиента и маршрутизацией на стороне сервера MVC. Фактически вы получаете ошибку 404 Page Not Found, потому что у сервера нет контроллера и действия для этого маршрута. Я подозреваю, что вы не обрабатываете ошибки, поэтому кажется, что ничего не происходит.

При перезагрузке http://localhost:5000/aboutus или если вы попытаетесь связать этот URL напрямую с ярлыком или, введя его в адресную строку (глубокую привязку), он отправит запрос на сервер. ASP.NET MVC попытается решить этот маршрут, и в вашем случае он попытается загрузить aboutusController и запустить действие Index. Конечно, это не то, что вы хотите, потому что ваш маршрут aboutus является компонентом Angular.

Что вам нужно сделать, так это создать способ для маршрутизатора ASP.NET MVC передавать URL-адреса, которые должны быть разрешены Angular обратно клиенту.

В вашем файле Startup.cs в методе Configure() добавьте маршрут "спа-спад" к существующим маршрутам:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");

    // when the user types in a link handled by client side routing to the address bar 
    // or refreshes the page, that triggers the server routing. The server should pass 
    // that onto the client, so Angular can handle the route
    routes.MapRoute(
        name: "spa-fallback",
        template: "{*url}",
        defaults: new { controller = "Home", action = "Index" }
    );
});

Создав маршрут, который указывает на контроллер и представление, который в конечном итоге загружает ваше приложение Angular, это позволит URL-адресам, которые сервер не обрабатывает, чтобы их передавать на клиент для правильной маршрутизации.

Ответ 2

В вашем Startup.cs добавьте это в метод Configure. Это должно быть перед другими операторами app.

app.Use(async (context, next) => {
    await next();

    if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value)) {
        context.Request.Path = "/index.html"; // Put your Angular root page here 
        await next();
    }
});

Ответ 3

Вам нужна эта маршрутизация в ASP.NET MVC

app.UseMvc(routes =>
{
     routes.MapRoute("Default", "{*url}",  new { @controller = "App", @action = "Index" });
});

Затем вам нужно настроить SystemJS с параметрами basePath

Ответ 4

Мое любимое решение - добавить следующий код в Global.asax.cs, который очень гладко и надежно справляется с проблемой:

     private const string RootUrl = "~/Home/Index";
     // You can replace "~Home/Index" with whatever holds your app selector (<my-app></my-app>)
     // such as RootUrl="index.html" or any controller action or browsable route

     protected void Application_BeginRequest(Object sender, EventArgs e)
        {
            // Gets incoming request path
            var path = Request.Url.AbsolutePath;

            // To allow access to api via url during testing (if you're using api controllers) - you may want to remove this in production unless you wish to grant direct access to api calls from client...
            var isApi = path.StartsWith("/api", StringComparison.InvariantCultureIgnoreCase);
            // To allow access to my .net MVCController for login
            var isAccount = path.StartsWith("/account", StringComparison.InvariantCultureIgnoreCase);
            if (isApi || isAccount)
            {
                return;
            }

            // Redirects to the RootUrl you specified above if the server can't find anything else
            if (!System.IO.File.Exists(Context.Server.MapPath(path)))
                Context.RewritePath(RootUrl);
        }

Ответ 5

Функция, которую вы ищете, это переписать URL. Есть два возможных способа справиться с этим. Классический способ - позволить IIS выполнять работу, как описано здесь:

fooobar.com/questions/295334/...

Если вы не хотите зависеть от IIS, вы можете обрабатывать это в промежуточном программном обеспечении ASP.NET 5, как показано в моем ответе здесь:

fooobar.com/questions/295335/...

Ответ 6

Вот еще два варианта решения этой проблемы. Вы можете добавить стратегию размещения хешей в свой модуль приложения.

import { LocationStrategy, HashLocationStrategy } from '@angular/common';

@NgModule({
imports: [.... ],
declarations: [...],
bootstrap: [AppComponent],
providers: [
{
  provide: LocationStrategy,
  useClass: HashLocationStrategy
}
]
})
export class AppModule { }

Этот параметр будет работать только для частей вашего приложения Angular2, которые живут на домашнем ASP-контроллере

Второй вариант - добавить маршруты к вашему ASP-контроллеру, которые соответствуют вашим маршрутам приложений Angular 2 и вернуть представление "Index"

public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    [ActionName("Angular-Route1")]
    public IActionResult AngularRoute1()
    {
        return View("Index");
    }

    public IActionResult Route2()
    {
        return View("Index");
    }
}

Ответ 7

Мне не повезло получить

 routes.MapRoute("Default", "{*url}",  
                  new { @controller = "App", @action = "RedirectIndex" });

работать. Я все еще получаю 404 с любым маршрутом на стороне клиента.

Update:
Выяснил, почему весь маршрут не работает: у меня был определенный маршрут атрибута ([Route("api/RedirectIndex")]), и в то время как простой маршрут можно получить с помощью обратного маршрута, он не срабатывал. Удаление маршрута атрибута заставило его работать.

Другим решением, которое работает так же просто, как и весь обработчик маршрутов, является просто создание настраиваемого обработчика, который запускается в конце конвейера промежуточного программного обеспечения в Configure():

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");

});

//handle client side routes
app.Run( async (context) =>
{
        context.Response.ContentType = "text/html";
        await context.Response.SendFileAsync(Path.Combine(env.WebRootPath,"index.html"));

});

Это в основном заканчивается тем самым маршрутом catch-all, который просто отправляет index.html через существующий запрос URL, если не было другого обработчика, который взял запрос.

Это прекрасно работает даже в сочетании с Правила перезаписи IIS (и в этом случае вышеуказанное просто не будет срабатывать.

Написал сообщение в блоге по этой теме:

Ответ 8

Вы использовали:

: [RouterOutlet, RouterLink] в компоненте.

Ответ 9

примените решение @ZOXEXIVO, тогда в вашем _Layout.cshtml добавьте следующее:

<head>
    <base href="/"/>
    .....
</had>

Ответ 10

Вы можете использовать как маршрутизацию когда вы вызываете Home/Index из маршрутизации angular.

написать

Home/Index.cshtml
<my-app></my-app>

app.routing.ts
    const routes: Routes = [
        { path: '', redirectTo: '/Home/Index', pathMatch: 'full' },
        { path: 'Home/Index', component: DashboardComponent }
    ]

Итак, когда URL-адрес будет Home/Index  будет загружать компонент активного URL-адреса, чтобы он загружал компонент панели инструментов.