.NET Core,Angular2,NancyFX - 404更改浏览器中的URL

时间:2017-09-28 08:40:42

标签: c# .net angular asp.net-core nancy

使用.NET Core静态文件提供应用程序时,我无法更改浏览器中的URL。这样做的时候我得到了

  

404 - 未找到

南希错误页面。

唯一有效的URL是基本URL localhost:5000。将URL更改为localhost:5000 / reservations会给我404.当不在基本URL上时按F5也会产生404。

如果我使用的是browsersync url,localhost:4200,一切正常,我可以更改URL并按F5而不用404.这是我在开发时所做的,但不是在使用IIS部署在服务器上时。

在IIS Express中运行应用程序

  1. ng build(将文件与index.html一起复制到wwwroot)

  2. 启动IIS Express

  3. Startup.cs

    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddEnvironmentVariables();
            Configuration = builder.Build();
    
            env.ConfigureNLog("nlog.config");
        }
    
        public IConfiguration Configuration { get; }
    
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddAuthentication(IISDefaults.AuthenticationScheme);
    
            services.AddMvc(config =>
            {
                var policy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();
                config.Filters.Add(new AuthorizeFilter(policy));
            });
    
            services.AddMvc();
    
            services.InjectServices();
    
            services.AddOptions();
    
            services.Configure<Endpoints>(Configuration.GetSection("Endpoints"));
    
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    
            services.AddSingleton<IConfiguration>(Configuration);
        }
    
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            app.Use(async (context, next) =>
            {
                await next();
                if (!context.Request.Path.Value.StartsWith("/api/"))
                {
                    context.Request.Path = "/index.html";
                    await next();
                }
            });
    
            app.UseDefaultFiles();
    
            app.UseStaticFiles();
    
            loggerFactory.AddNLog();
    
            app.AddNLogWeb();
    
            app.UseOwin(x => x.UseNancy(new NancyOptions
            {
                Bootstrapper = new Bootstrapper(app)
            }));
        }
    }
    

    Bootstrapper.cs

    public class Bootstrapper : DefaultNancyBootstrapper
    {
        readonly IApplicationBuilder _app;
    
        public Bootstrapper(IApplicationBuilder app)
        {
            _app = app;
        }
    
        protected override void ConfigureApplicationContainer(TinyIoCContainer container)
        {
            base.ConfigureApplicationContainer(container);
    
            container.Register<IOptions<Endpoints>>(_app.ApplicationServices.GetService<IOptions<Endpoints>>());
    
            container.Register<IReservationService>(_app.ApplicationServices.GetService<IReservationService>());
        }
    }
    

    wwwroot的

    enter image description here

    的index.html

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <title>XXX</title>
        <base href="/">
        <meta name="viewport" content="width=device-width,initial-scale=1">
        <link rel="icon" type="image/x-icon" href="XXX">
        <link href="styles.61cc257ef8131303860b.bundle.css" rel="stylesheet" />
    </head>
    <body>
        <app-root></app-root>
        <script type="text/javascript" src="inline.f68c652d205feae6e02a.bundle.js"></script>
        <script type="text/javascript" src="polyfills.756a44edc7e0a68ce65c.bundle.js"></script>
        <script type="text/javascript" src="vendor.940a3ce39a746f717f7b.bundle.js"></script>
        <script type="text/javascript" src="main.d5f9dd82a3600822cae2.bundle.js"></script>
    </body>
    </html>
    

    我知道从服务器处理静态内容时存在一些问题,但我似乎无法弄明白。

    在.NET Core中托管Angular应用程序时,如何使用浏览器URL进行导航?

    更新1:

    添加后:

    PerformPassThrough = (context => context.Response.StatusCode == HttpStatusCode.NotFound)
    

    404错误消息消失,但页面现在为空,没有任何错误消息,除了控制台中的404 ..

    enter image description here

3 个答案:

答案 0 :(得分:0)

IMO您编写的中间件应该在app.UseDefaultFiles()之后;和app.UseStaticFiles(); 而您只处理API请求。尝试重写一点,以处理404错误,并且不处理带扩展名的请求:

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

    if (context.Response.StatusCode == 404
        && !Path.HasExtension(context.Request.Path.Value)
        && !context.Request.Path.Value.StartsWith("/api/"))
    {
        context.Request.Path = "/index.html";
        await next();
    }
});

答案 1 :(得分:0)

您需要删除第一个await next();。这是在将网址重写为/reservations之前将请求发送到管道的index.html

当它击中Nancy时,它会看到它是否可以处理/reservations,它不能处理,并呈现404页面。

答案 2 :(得分:0)

  1. 修改后的Startup.cs
  2. 添加了为所有请求返回index.html的模块。
  3. 在bootstrapper.cs中配置了根路径。
  4. <强> Startup.cs

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        //For serving index.html on baseurl - this can we done in AppNancyModule aswell: Get("/", _ => View["index"]);
        app.UseDefaultFiles();
    
        app.UseStaticFiles();
    
        loggerFactory.AddNLog();
    
        app.AddNLogWeb();
    
        app.UseOwin(x => x.UseNancy(new NancyOptions
        {
            Bootstrapper = new Bootstrapper(app, env)
        }));
    }
    

    <强> AppNancyModule

    public class AppNancyModule : NancyModule
    {
        public AppNancyModule()
        {
            //Get("/", _ => View["index"]);
    
            Get(@"^(.*)$", _ => View["index"]);
        }
    }
    

    <强> Bootstrapper.cs

    public class AppRootPathProvider : IRootPathProvider
    {
        private readonly IHostingEnvironment _environment;
    
        public AppRootPathProvider(IHostingEnvironment environment)
        {
            _environment = environment;
        }
        public string GetRootPath()
        {
            return _environment.WebRootPath;
        }
    }
    
    public class Bootstrapper : DefaultNancyBootstrapper
    {
        readonly IApplicationBuilder _app;
    
        protected override IRootPathProvider RootPathProvider { get; }
    
        public Bootstrapper(IApplicationBuilder app, IHostingEnvironment environment)
        {
            RootPathProvider = new AppRootPathProvider(environment);
            _app = app;
        }
    
        protected override void ConfigureApplicationContainer(TinyIoCContainer container)
        {
            base.ConfigureApplicationContainer(container);
    
            container.Register<IOptions<Endpoints>>(_app.ApplicationServices.GetService<IOptions<Endpoints>>());
    
            container.Register<IReservationService>(_app.ApplicationServices.GetService<IReservationService>());
        }
    }