Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Core (HttpSys) Routing works locally but not when deployed

For some reason when I'm running my ASP.NET Core API using HttpSys on a windows server (through service fabric) the routing doesn't work whereas locally everything works. The thing is that the middleware works fine, so I know that the request is being processed but it's never able to hit any controller, it just defaults to my app.run("Some 404 response") 404 middleware. Some of my code:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    #region IOC
    //ommitted
    #endregion 

    services.AddAutoMapper(typeof(SomeModel));

    services.AddCors(c => 
    {
        c.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
    });

    services.AddDbContext<SomeContext>(options => options.UseSqlServer(_configuration.GetConnectionString("Dev")));

    services.AddMvc().AddFluentValidation();
}        

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        IdentityModelEventSource.ShowPII = true;
    }

    //Eliminating that auth is the problem
    //app.UseAuthentication(); 

    if (env.IsProduction())
    {
        app.UseHsts();
        app.UseHttpsRedirection();
    }

    app.UseCors("AllowOrigin");
    app.UseMvcWithDefaultRoute(); //tried this instead of below. No luck

    //app.UseMvc();

    app.Use((context, next) =>
    {
        if (context.Request.Path.Value == "" || context.Request.Path.Value == "/")
        {
            context.Response.ContentType = "text/plain";
            return context.Response.WriteAsync("We're running!");
        }

        return next.Invoke();
    });

    app.Run(context =>
    {
        context.Response.StatusCode = 404;
        context.Response.ContentType = "application/json";

        return context.Response.WriteAsync("{ \"message\": \"Not found\" }");
        });
    }
}

Program.cs:

public static void Main(string[] args)
{
    using (var scope = host.Services.CreateScope())
    {
        var services = scope.ServiceProvider;
        try
        {
            var context = services.GetRequiredService<SomeContext>();
            DbInitializer.Initialize(context);
        }
        catch (Exception ex)
        {
            logger.Error(ex, "An error occured while seeding the database");
        }
    }

    host.Run();
}
public static IWebHost CreateWebHostBuilder(string[] args)
{
    IHostingEnvironment env = null;

    var builder = 
        WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
           env = hostingContext.HostingEnvironment;
        })
        .UseHttpSys(options =>
        {
            if (!env.IsDevelopment())
            {
                options.UrlPrefixes.Add("https://*:30010/BasePathOfAPI/");
            }
            else
            {
                options.UrlPrefixes.Add("http://localhost:5000/BasePathOfAPI/");
            }
        })
        .ConfigureLogging(b =>
        {
            b.AddApplicationInsights("id here");
        })
        .UseNLog()
        .Build();

    return builder;
}

So the setup is almost similar apart from the UrlPrefixes. The fact that I can both through a gateway and on the windows server call https://somehost/BasePathOfAPI/ and get the message We're running! displayed in the browser tells me that the API is up and running but it's simply not able to hit any of the controllers if I try. One example of a controller:

[Route("api/{someNumber:int}/Home")]
[ApiController]
public class HomeController: ControllerBase
{
    //ctor and props ommitted

    [HttpGet("GetSomeData")
    [ProducesResponseType(StatusCodes.200OK)]
    public async Task<IActionResult> GetSomeData()
    {
        //implemenetation
    }
}

Now, the url I'm using to try and get to the above controller is:

https://somehost/BasePathOfAPI/api/1234/Home/GetSomeData

Which returns in a 404 message: not found, however if I locally run:

http://localhost:5000/BasePathOfAPI/api/1234/Home/GetSomeData

It works fine.

Not sure where I'm going wrong, maybe something with the UrlPrefixes but should I then be able to get to the middleware if that's incorrect? Maybe something with the routing, but then why does it work locally?

like image 570
Force444 Avatar asked Aug 07 '19 22:08

Force444


1 Answers

Solved - The full path base must be added to the UrlPrefix and the urlacl registration so

netsh http add urlacl url=https://*:30010/BasePathOfAPI/ user="NT AUTHORITY\NETWORK SERVICE" 

and in addition to this as controllers are in another dll, the assembly must be referenced in the ConfigureServices method:

services.AddMvc().AddApplicationPart(typeof(SystemController).Assembly)

These two fixes made it work

like image 105
Force444 Avatar answered Oct 16 '22 12:10

Force444