Url Rewrite for hosted application on IIS - asp.net-mvc-4

I have developed asp.net mvc core 3.0 web application and deployed in windows server. I would like to hide controller name in url.
Example :
orginal url : www.example.com/test/authenticate/login
expected url : www.example.com/test/login
Im not sure about it by achieve it code or IIS.
startup.cs route code.
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});

Use Attribute routing:
[Route("/")]
public class AuthenticateController : ControllerBase
{
[HttpGet("login")]
public IActionResult Get()
{
return Ok("Ok");
}
}

Related

404 not found - IIS 7.5 (sub-application)

I have a main application (Toolbox-GUI) and a sub application (Toolbox-WPS) deployed on IIS 7.5.
The Api under sub-application is giving 404 not found when deployed on server.
When run Locally(localhost) it works fine. I am using .netcore
Both have different application pools. both application pools are set at .net framework version 4.0/ApplicationPoolIdentity.
The main project works fine.
Toolbox-WPS (subapplication)
[Route("wps/status/{id}")]
[HttpGet]
public ActionResult GetStatusRecord(long id)
{
// returns the status document for a given status id
//logger.Debug("GET wps/status/" + id);
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfiguration>(Configuration);
//services.AddControllersWithViews();
services.AddControllers();
services.AddSingleton<ISingleton, WPSGlobalSettings2>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
WPSGlobalSettings.Configure(env);
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "DefaultApi",
// added the web api to a specified url/wps publish path, so can remove this here.
pattern: "{controller}/{id}"
//defaults: new { id = RouteParameter.Optional }
);
});
}
Toolbox-GUI (main app)
function poll_check() {
$.ajax({
url: pollStatusUri,
type: "GET",
success: function (data) {
// if (debugState) console.log("polling at " + pollStatusUri);
},
dataType: 'json'
});
IIS Configuration
main app
sub app
project hierarchy
application pools
main app
sub app

ASP.NET Core 5: OpenIDConnect breaking default/root route

I have an ASP.NET Core 5 MVC app, with the default/root route set like this inside PageController:
[AllowAnonymous]
[Route("/")]
public IActionResult __Home(int? parent)
{
return View();
}
This worked fine until I added OpenIdConnect authentication. After that, the root (/) page no longer routes to __Home in the PageController, it just returns a blank page. All other pages route just fine.
When I comment out this:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration, "AzureAdB2C");
then / works again, so I know it's something to do with the authentication. As you can see, I have added [AllowAnonymous] to that action.
I have this in my startup:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"
);
});
Any ideas on how to fix this? I know it's unconventional to have the default/root route in a weird controller/action like that, but there are reasons for it, so I'm hoping it can still work.
More Info:
I found that if I move app.UseEndpoints above app.UseAuthentication, then the home page shows. After logging in (with B2C), however, it goes into an infinite loop (i.e. the authentication token doesn't stick?).
EDIT: My Startup.cs class
using Blank.Models;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Identity.Web;
namespace Blank
{
public class Startup
{
private readonly AppSettings appSettings = null;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
this.appSettings = new AppSettings();
this.Configuration.Bind(this.appSettings);
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration, "AzureAdB2C");
services.AddSession();
services.Configure<OpenIdConnectOptions>(Configuration.GetSection("AzureAdB2C"));
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
services.Configure<AppSettings>(this.Configuration);
services.AddEntityFrameworkSqlServer().AddDbContext<BlankDBContext>(
Options => Options.UseSqlServer(Microsoft.Extensions.Configuration.ConfigurationExtensions.GetConnectionString(this.Configuration, "BlankDatabase"))
);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseSession();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Page}/{action=Index}/{id?}");
});
}
}
}
Edit 2
I think that app.UseAuthentication() is breaking/returning the blank page, because when I put the following code before app.UseAuthentication() I get something on the home page, and if it's after then blank:
app.Use(async (context, next) =>
{
var endpoint = context.GetEndpoint();
if (endpoint != null)
{
await context.Response.WriteAsync("<html> Endpoint :" + endpoint.DisplayName + " <br>");
if (endpoint is RouteEndpoint routeEndpoint)
{
await context.Response.WriteAsync("RoutePattern :" + routeEndpoint.RoutePattern.RawText + " <br>");
}
}
else
{
await context.Response.WriteAsync("End point is null");
}
await context.Response.WriteAsync("</html>");
await next();
});
So perhaps it has to do with my authentication? Here's my appsettings.json:
"AzureAdB2C": {
"Instance": "https://abc.b2clogin.com",
"Domain": "abc.onmicrosoft.com",
"ClientId": "62...f1",
"TenantId": "7e...ae",
"SignUpSignInPolicyId": "B2C_1_SUSI",
"SignedOutCallbackPath": "/"
},
Turns out the problem was this in my appsettings.json:
"SignedOutCallbackPath": "/"
Removing this fixed the problem, and the home page now loads correctly.

Swagger API breaks when Route attribute is set to Controller Action - ASP.NET Core

I am using ASP.NET Core 3.1. In My Web Application I have integrated swagger. Which works fine, shows the endpoints properly in the swagger API documentation. The code in startup is as below:
public void ConfigureServices(IServiceCollection services)
{
services.AddSwaggerGen( c => {
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Clients}/{action=Index}/{id?}");
});
app.UseSwagger();
app.UseSwaggerUI(c => {
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Push Notification API V1");
});
}
To my Error Controller I just added a HttpStatusCodeHandler method and gave a route as below.
Then the swagger gives a error as:
"Failed to load API definition." Fetch error undefined
/swagger/v1/swagger.json
The method code is as follows.
[Route("Error/Error/{statusCode}")]
public IActionResult HttpStatusCodeHandler(int statusCode)
{
switch (statusCode)
{
case 404:
ViewBag.ErrorMessage = "Sorry, the resource you requested could not be found.";
break;
}
return View("Error");
}
Every time I comment out the Route attribute [Route("Error/Error/{statusCode}")] the swagger API works fine. What could be the error in this?
I removed the [Route("Error/Error/{statusCode}")] from the method and included the middleware app.UseStatusCodePagesWithRedirects() in the configure method.
I am not sure on the exact reason for the swagger API error.
The root cause is your controller is recognized as ApiController if you add Route attribute, and swagger will be broken if you do not add HttpMethod attribute in your controller.
Add [ApiExplorerSettings(IgnoreApi = true)] attribute to your controller, and the swagger broken problem should be fixed.

Asp.net core web api custom error response for unmatched controller action?

I have an issue with ASP.NET Core Web API, where I want to display a custom error message model if non of the controller actions were matched.
So, it would be a 404 error but with a customized body.
I haven't tried anything because I am not sure if this is even possible.
You can add a catch-all route by adding an action method with a route that will always match if no other does.
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(
name: "CatchAll",
template: "{*url}",
defaults: new { controller = "CatchAll", action = "Index" });
});
For Web API:
public class CatchAllController : Controller
{
[HttpGet("{*url}", Order = int.MaxValue)]
public IActionResult Index()
{
return NotFound(YourModel)
}
}
For MVC:
public class CatchAllController : Controller
{
public IActionResult Index()
{
Response.StatusCode = StatusCodes.Status404NotFound;
return View();
}
}
app.UseExceptionHandler(errorApp =>
{
errorApp.Run(async context =>
{
context.Response.StatusCode = 500;
});
});
Using this middleware you can actually catch the code and then handle it accordingly. It's taken from this page
. There are various other examples in the link some simpler ones might fit you better

Swashbuckle root error when i deploy on subfolder

I begin with Swashbuckle, i make a Web API in .NET Core with Swashbuckle.
I need to deploy my API in a sub-application of an IIS site
IIS infrastructure
IIS Site (site)
myApi (subApplication)
http://ip:80/myApi
I would like the access to swagger UI to be done via this url :
http://ip:80/myApi/swagger
I would like the access to the methods to be done by this url :
http://ip:80/myApi/api/[controller]/methode
ConfigureServices(IServiceCollection services)
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info { Title = "My REST API", Version = "v1" });
});
Configure(IApplicationBuilder app..)
if (env.IsEnvironment("ProdIT"))
{
app.UseSwagger(c =>
{
c.PreSerializeFilters.Add((swaggerDoc, httpReq) => swaggerDoc.BasePath = "/myApi/");
c.RouteTemplate = "myApi/api-docs/{documentName}/swagger.json";
});
app.UseSwaggerUI(c =>
{
c.RoutePrefix = "myApi/swagger";
c.SwaggerEndpoint("/myApi/api-docs/v1/swagger.json", "MY REST API V1");});
Route Controller
[Route("api/[controller]")]
Could you tell me what's wrong with my code?
Thanks in advance
I had the same issue and I resolved it by configuring the SwaggerUI like that;
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("v1/swagger.json", "MY REST API V1");});
}