asp .net core redirect inside midleware - asp.net-core

I want to create a page allowing to create the database and initialize the default data of an application for each new deployment. for that I create a middleware which checks if it is possible to connect to the database. in the event that it is not possible to connect to the database (which means that the database does not yet exist), the middleware redirects to an action of the application responsible for collecting the default data and proceed with the creation of the database.
However, in the middleware the redirect does not work despite all attempts except for a redirect to an external site such as google.com.
I use asp.net core 2.2 and entityframework core
MissingDatabaseMiddleware.cs
public class MissingDatabaseMiddleware
{
private readonly RequestDelegate _next;
private readonly string _missingTenantUrl;
public MissingDatabaseMiddleware(RequestDelegate next, string missingTenantUrl)
{
_next = next;
_missingTenantUrl = missingTenantUrl;
}
public async Task Invoke(HttpContext httpContext, MydbContext context)
{
if (!context.Database.CanConnect())
{
httpContext.Response.Redirect(_missingTenantUrl, false);
return;
}
await _next.Invoke(httpContext);
}
}
startup.cs
public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHostingEnvironment env, MydbContext, ILoggerFactory loggerFactory){
app.UseMiddleware<MissingDatabaseMiddleware>("/Setup/AppSetup");
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
});
}

the solution is to add a check in the request url
public async Task Invoke(HttpContext httpContext, MemoryDbContext context)
{
if (!context.Database.CanConnect() && !httpContext.Request.GetEncodedUrl().Contains(_missingTenantUrl))
{
httpContext.Response.Redirect(_missingTenantUrl, false);
return;
}
await _next.Invoke(httpContext);
}

Related

CORS issue with PUT request from reactjs to asp.netCore api

I am working on a Reactjs app with Asp.netCore API with Sql database
deployed to IIS server.
All the operation is working except PUT operation on the task
it break with CORS error and the request is not reaching the backend, I tested it locally and it's working fine. Tested using Postman and it's working too even the deployed version is working with postman. I can't figure out what's the issue or from where I should start debugging.
startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(o => o.AddPolicy(name: CorsPolicy, builder =>
{
builder.WithOrigins(FrontEnd_URL).SetIsOriginAllowed((host) =>
true).AllowAnyHeader().AllowAnyMethod().AllowCredentials();
}));
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseCors(CorsPolicy);
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapHub<TrelloHub>("/trello");
});
}
TaskController
[Route("/api/tasks")]
[ApiController]
public class TasksController : Controller
{
private readonly IMapper _mapper;
private readonly ITaskService _taskService;
public TasksController(ITaskService taskService , IMapper mapper)
{
_mapper = mapper;
_taskService = taskService;
}
[HttpPut("{id:int}", Name = "UpdateTask")]
public async Task<String> UpadateTask([FromBody]TaskDto taskdto, int id)
{
var taskModel = _mapper.Map<Task>(taskdto);
return await _taskService.UpadateTask(id , taskModel);
}
}
first check IIS server logs. it can help you a lot, also look at the request headers of the reactjs client origin: header exactly and add it to the allowed origins

ASP.NET core Web API routing

Route using "UseMvc" but not able to call the controller
In startup page have added service.AddMvc method & in configure section it's app.useMvc()
I am not able to route and can't figure out what the problem is
The controller code is here and have route : the action method is Get with parameter start of DateTime type
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<CurrencyContext>(cfg => {
cfg.UseSqlServer(_config.GetConnectionString("BitCoinIndexConnectionString"));
});
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseStaticFiles();
app.UseNodeModules(env);
app.UseMvc(routes =>
{
routes.MapRoute(name: "default",
template: "api/{controller}/{action}/{start:DateTime}",
defaults: new {
controller = "Currency",
action = "Get",
start = DateTime.Now.AddDays(-14)});
});
}
}
[Route("api/[Controller]")]
public class CurrencyController : Controller
{
private BitCoinRepository<BitCoinIndex> _repository;
public CurrencyController(BitCoinRepository<BitCoinIndex> repository)
{
_repository = repository;
}
// GET: api/<controller>
[HttpGet("{start}",Name ="Get")]
public IActionResult Get(DateTime start)
{
// var bci = _repository.GetByDates(start).ToDictionary(t => t.Date.ToString(), t => t.Rate);
return View();
}
}
I faced the same issue and resolved it using attribute routing. This is what I did. If you are not using .Net Core 3, ignore point 1.
1st disable endpoint routing by adding this in your ConfigureServices:
services.AddMvc(options => options.EnableEndpointRouting = false);
You can now use this in Configure method
app.UseMvc();
Next, just define your routes inside the controller (bear in mind I generally prefer routing by adding routes to the routing table, but encountered unnecassary issues going this 'route', attribute routing was the easiest 'route' to take).
[Route("api/myctrl")]
[ApiController]
public class MyControllerController : ControllerBase
{
[HttpGet]
[Route("getsomething")]
public async Task<JsonResult> DoStuff()
{
}
}
Access this by either using #Url.Action("DoStuff", "MyController"); or /api/myctrl/getsomething

Hangfire Dashboard .net core - authentication works locally, not on server

I've implemented authentication for Hangfire Dashboard as recommended (the Dashboard isn't viewable on the server without authentication).
It wasn't working on the server, so I just set Authorize to always be true:
In startup.cs:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//Other stuff here
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
Authorization = new[] { new MyAuthorizationFilter() }
});
}
In my own class:
/// <summary>
/// Used for Hangfire Dashboard only
/// </summary>
public class MyAuthorizationFilter : IDashboardAuthorizationFilter
{
public bool Authorize(DashboardContext context)
{
return true;
}
}
However, even this gets a 403 error returned - yet it works fine locally. The previous auth also works fine locally but not on the server.
I've searched Google but can't find anyone having this error - how can I fix it?
Thanks.
for worked like below:
class MyAuthorizationFilter : IDashboardAuthorizationFilter
{
public bool Authorize(DashboardContext context)
{
var httpContext = context.GetHttpContext();
// Allow all authenticated users to see the Dashboard (potentially dangerous).
return httpContext.User.Identity.IsAuthenticated;
}
}
And in startup method use as below:
app.UseAuthentication();
app.UseHangfireDashboard(options: new DashboardOptions()
{
Authorization = new IDashboardAuthorizationFilter[]
{
new MyAuthorizationFilter()
}
});
app.UseHangfireServer();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

Ignoring Request in middleware

So I want IIS to basically not do anything when certain urls are requested bacause I want react router to which I have rendered from serverside, to handle the request.
Used this link
I have created a middleware that checks each request. Now i dont know how to ignore or abort this request once I find the right urls.
public class IgnoreRouteMiddleware
{
private readonly RequestDelegate next;
// You can inject a dependency here that gives you access
// to your ignored route configuration.
public IgnoreRouteMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
if (context.Request.Path.HasValue &&
context.Request.Path.Value!="/")
{
// cant stop anything here. Want to abort to ignore this request
}
await next.Invoke(context);
}
}
If you want to stop a request, just don't call next.Invoke(context), because this will call the next middleware in the pipeline. Not calling it, just ends the request (and the previous middlewares code after it's next.Invoke(context) will be processed).
In your case, just move the call to the else branch or just negate the if expression
public class IgnoreRouteMiddleware
{
private readonly RequestDelegate next;
// You can inject a dependency here that gives you access
// to your ignored route configuration.
public IgnoreRouteMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
if (!(context.Request.Path.HasValue && context.Request.Path.Value!="/"))
{
await next.Invoke(context);
}
}
}
Also make sure to read the ASP.NET Core Middleware documentation for a better understanding on how middlewares work.
Middleware is software that is assembled into an application pipeline to handle requests and responses. Each component:
Chooses whether to pass the request to the next component in the pipeline.
Can perform work before and after the next component in the pipeline is invoked.
But if you want server-sided rendering, consider using Microsoft`s JavaScript/SpaServices library, which is already built in in the newer templates (ASP.NET Core 2.0.x) and register a fallback route such as.
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});
The new templates also come with support for hot module replacement

Add custom query parameter to action URL in ASP.NET Core MVC

In ASP.NET Core MVC, I'd like to make it so that URLs created with Url.Action and action-based tag helpers include a custom query parameter in the URL. I want to apply this globally, regardless of the controller or action.
I tried overriding the default route handler, which worked at one time, but broke with an ASP.NET Core update. What am I doing wrong? Is there a better way?
Try adding it to the collection instead of overriding the DefaultHandler. The following worked for me on version 1.1.2:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// ... other configuration
app.UseMvc(routes =>
{
routes.Routes.Add(new HostPropagationRouter(routes.DefaultHandler));
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
// ... other configuration
}
Here's the router, just for completeness.
public class HostPropagationRouter : IRouter
{
readonly IRouter router;
public HostPropagationRouter(IRouter router)
{
this.router = router;
}
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
if (context.HttpContext.Request.Query.TryGetValue("host", out var host))
context.Values["host"] = host;
return router.GetVirtualPath(context);
}
public Task RouteAsync(RouteContext context) => router.RouteAsync(context);
}