web-dev-qa-db-ja.com

ASP.NET 5 + Angular 2ルーティング(テンプレートページは再読み込みされません)

Angular 2ベータ版では、デフォルトでhtml5ルーティングが使用されます。ただし、コンポーネントに移動してルートが変更された場合(たとえば http:// localhost:5000/aboutus )およびページをリロード/リフレッシュしても、何もありません

この問題は、このpostでも発生しました。答えのほとんどは、HTML5ルーティングをangular 2で追求する場合、このルーティングの問題はサーバー側で処理する必要があると述べています。詳細な議論ここ

Asp.netサーバー環境を使用してこの問題を処理する方法がわかりません。

任意のangular asp.netを使用してこの問題に遭遇した2人の開発者はいますか?

PS。 ASP.NET 5を使用しています。私のAngular 2つのルートはMVCルートを使用しています。

22
raberana

表示されている問題は、AngularクライアントでのルーティングとMVCサーバー側のルーティングの違いに関係しています。サーバーにはないため、実際には_404 Page Not Found_エラーが発生しています。そのルートのコントローラーとアクションがあります。エラーを処理していないのではないかと思われます。

_http://localhost:5000/aboutus_をリロードするとき、またはショートカットから直接、またはアドレスバーに入力して(ディープリンク)、そのURLにリンクしようとした場合、サーバーに要求を送信します。 ASP.NET MVCはそのルートを解決しようとし、あなたの場合はaboutusControllerをロードしてIndexアクションを実行しようとします。もちろん、あなたのaboutusルートはAngularコンポーネントです。

行うべきことは、ASP.NET MVCルーターがURLを渡す方法を作成することです。URLは、Angularによって解決される必要があります。

_Startup.cs_ファイルのConfigure()メソッドで、既存のルートに「spa-fallback」ルートを追加します。

_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を適切なルーティングのためにクライアントに渡すことができます。

19
Brad Rem

あなたの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();
    }
});
8
Jaanus

私のお気に入りの解決策は、問題を非常にスムーズかつ確実に処理する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);
        }
6
Methodician

ASP.NET MVCでこのルーティングを使用する必要があります

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

次に、basePathオプションを使用してSystemJSをセットアップする必要があります

5
ZOXEXIVO

運がない

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

動作するように。私はまだクライアント側のルートで404を受け取ります。

更新:
キャッチオールルートが機能しなかった理由を理解しました。定義済みの属性ルート([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"));

});
_

これは、基本的に、他のハンドラーがリクエストを取得しなかった場合に、既存のURLリクエストを介して単にindex.htmlを送信するキャッチオールルートになります。

これは、 IIS Rewrite rules と組み合わせてもうまく機能します(この場合、上記は実行されません。

このトピックに関するブログ投稿を書きました:

2
Rick Strahl

探している機能はURLの書き換えです。これを処理する方法は2つあります。ここで説明するように、古典的な方法はIISに仕事をさせることです:

https://stackoverflow.com/a/25955654/32074

IISに依存したくない場合は、代わりに、ASP.NET 5ミドルウェアでこれを処理できます。ここでの私の回答に示します。

https://stackoverflow.com/a/34882405/32074

2
Bill

この問題を解決するためのオプションが2つあります。ハッシュロケーション戦略をアプリモジュールに追加できます。

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

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

このオプションは、Angular2アプリのHome ASP Controllerに存在する部分に対してのみ機能します

2番目のオプションは、ASPコントローラに一致するルートを追加しますAngular 2つのアプリルートと「インデックス」ビューを返す

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

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

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

angularルーティングからHome/Indexを呼び出すときに、両方のルーティングを使用できます。

書く

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のコンポーネントがロードされるため、ダッシュボードコンポーネントがロードされます。

0
Engineer

上記の選択されたソリューションは私にはうまくいきませんでした。Tへのすべてのコメントをフォローした後、404を受け取りました。MVC5アプリでangle5アプリを使用しています。デフォルトのインデックスランディングページを、angular5の開始点として使用します。 My angular appはmvcroot/ClientApp /という名前のフォルダーにありますが、ngビルドでは、.angular-cli.jsonファイルの1つの設定を変更して、mvcroot/Dist /に分散ファイルを配置します。 outDir ":" ../Dist "

ただし、このソリューションは機能しました。

この方法では、Distディレクトリ内のルートのみがフォールオーバーします。これで、毎回更新を実行し、正しいコンポーネントにとどまりながら、angular5アプリの正確なルートをリロードできます。キャッチをすべて最初に置くようにしてください。サイドノートで、angular5でトークン認証を使用する場合、リフレッシュを押すとトークンをグローバル変数に保存する可能性があるすべてのメモリが消去されるため、トークンをwindow.localStorage(またはangular5アプリの外部にある他のメカニズム)に保存します。これにより、ユーザーが更新した場合に再度ログインする必要がなくなります。

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Catch All",
                "dist/{*url}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional });

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }


            );
0
RandallTo

使用しましたか:

ディレクティブ:コンポーネントの[RouterOutlet、RouterLink]。

0
Sachin

@ZOXEXIVOのソリューションを適用し、_Layout.cshtmlに以下を追加します。

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