How to override the AbpUserConfigurationController? - asp.net-core

I don't know the underlying principle of the AbpUserConfigurationController? How does it inject into the aspnet core DI container? Why can't it be seen on the Swagger page? I'm using the aspnetboilerplate Premium Startup Templates.

To override AbpUserConfigurationController
you can use the approach mentioned in aspnetboilerplate/#3296(comment)
To understand how Abp inject controller into AspNetCore project
It is explained by #tseng , controller can be added via AddApplicationPart of ApplicationPartManager.
There are a few places that Abp uses ApplicationPartManager to include additional controllers.
In Abp.AspNetCore, as pointed out by #tseng, at AbpAspNetCoreModule#L47-78, the implementation here is to include Controller created in the Abp.AspNetCore assembly.
In the downloaded template, you can look for *WebCoreModule.cs under *.*.Web.Core project. The following code snippet is another place that Abp converts all the application services in the MyProjectApplicationModule assembly into controllers.
Configuration.Modules.AbpAspNetCore()
.CreateControllersForAppServices(
typeof(MyProjectApplicationModule).GetAssembly()
);
Also you take a look at AbpAspNetCoreConfiguration.cs#L47-L55 where the ControllerAssemblySettings is being updated.
Take note that CreateControllersForAppServices is called in PreInitialize() of AbpModule and AddApplicationParts is called in PostInitialize() of AbpAspNetCoreModule.
Therefore, the ControllerAssemblySettings used in the method AddApplicationParts of AbpAspNetCoreModule has already contains all the controllers to be added via ApplicationPartManager
To understand why AbpUserConfigurationController not showing up in swagger-ui
In short, conventional routing is not supported by Swagger, see swashbuckle-apiexplorer-and-routing.
TokenAuthController showed up in the swagger-ui because it is decorated with [Route("api/[controller]/[action]")] (attribute routing)

Related

ASP.NET Transfer data from controller action

There is a sales service implemented as a Telegram bot. I need to create a website control panel for this service. Since the service is a .NET application I am thinking to use ASP.NET Core technology.
How do I transfer data from the controller action to the Program class containing all the functionality of the service (maybe it is worth defining the Program as a static class)?
You may have misunderstood Asp.Net Core. .net core adopts the pipeline mode, that is, when you call the action in the controller, it will enter the middleware pipeline of Program.cs(.net 5 is Startup.cs), and execute in sequence according to the order of your middleware, adopting the principle of first in, last out. This means that if you follow the normal .net core logic, the value you get in the controller (except the parameters defined in the URL), you cannot pass it into Program.cs. When you successfully enter the action of the controller, Program.cs has been executed.
Not sure what your sales service looks like, but I think you can register it as a service and use it in your controllers using dependency injection.
Helpful link: ASP.NET Core Middleware.

Accessing HTTP Headers in ASP.Net Core Business Logic

I am using ASP.Net core and I have a requirement to access a specific HTTP Header in a business logic class (not a controller or action).
To provide a full picture of the configuration here, I have a custom ASP.Net Core Middleware which based on some logic will add a value into a custom HTTP Header, it is the value from this header that I need to access in the business logic class.
Currently the way that I achieve this is to inject an HttpContextAccessor, using the following DI registration.
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
In the class which requires access to the HTTP Headers I then request an IHttpContextAccessor using constructor injection and use this to access the relevant HTTP Header.
Doing the above works fine and gives me the results that I require, looking around various articles on the Internet however the general consensus appears to be to avoid using HttpContext.Current in ASP.Net Core.
If the above is the case, is there a better way for my business logic class to access the value that my custom middleware is inserting into a custom HTTP Header?
I should be clear, whilst at present the middleware is storing the required value in a HTTP Header for use by the business logic class, I am open to other methods of the middleware making the required value available to the business logic class if there is a better approach.
Any questions or clarifications, please let me know.
There is no HttpContext.Current in ASP.Net Core, so it's easy to avoid using it. You would have to implement your own extension method if you wanted it, but the general feeling in the .Net Core community is that it's much better to use IHttpContextAccessor.
In earlier versions of .Net Core an implementation of IHttpContextAccessor was auto registered in the DI container. In more current version you have to register it yourself with the line of code you mentioned:
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
Injecting IHttpContext into your method that needs access to the headers is a workable approach. Or if you like you could use a helper method that places a copy of the headers in a simpler structure and then pass that object in to your class since it doesn't really need access to the full HttpContext.

How does ASP.Net MVC resolve controllers?

I'm trying to build an asp.net mvc 4 application.
I want the application to encompass both a HTML site and a restful api, e.g.
www.mysite.com/MyDetails/
www.mysiste.com/api/users/{userid}/Details/
In the above example I would use 2 controller classes.
MyDetailsController which inherits from System.Web.Mvc.Controller
DetailsController which inherits from System.Web.Http.ApiController
I've also added a simple 'Users Route' to the WebApiConfig:
routeTemplate: "api/users/{userid}/{controller}/{id}
In my early testing it appears as though the following scenarios are invalid:
www.mysite.com/api/users/12345/MyDetails/
www.mysite.com/Details/
Both of those return a 404.
This is definitely a good thing but what I'm trying to find out is why doesn't it work?
Can I rely on it not working or is it just coincidence in my simple test?
I've read about people struggling to develop a single MVC app/project that encompasses both HTML and REST apis but the most common complaint seems to be you can't duplicate controller names and it still seems like you can't simply use a namespace to differentiate them.
In this example I've deliberately designed the class names to avoid any conflict so what other gotchas are waiting to trip me up?
Thanks,
Chris A
Check your routes file, should be Global.asax under RegisterRoutes. The MapRoute call should tell you everything you need to know for MVC routing. Keep in mind, the order of the routes is important: top routes take priority over the bottom. Web API uses the WebApiConfig class and MapHttpRoute call to configure routes.
Please ensure you have put a (MVC) route on top of the action you wish to hit of your controller, default action being index.
[System.Web.Mvc.Route("Help")]
public ActionResult Index()
{
ViewBag.DocumentationProvider = Configuration.Services.GetDocumentationProvider();
return View(Configuration.Services.GetApiExplorer().ApiDescriptions);
}
Code above will hit this action method (provided your controller is registered and derived either from apiController or Controller) in the following way:
http://localhost:54541/help inside your IISExpress.
To register please do the following:
In "global.asax.cs", you’ll need to add:
AreaRegistration.RegisterAllAreas();

ActionFilter is not executing in WebApplication but executing in WebApi

I have created an ActionFilterAttribute
public class LoggingNHibernateSessionAttribute : ActionFilterAttribute
The purpose of the filter as name indicates is logging and opens and commits a transaction, before and after target action respectively.
I have a WebApi(myAPI) project (MVC4) and a WebApplication(myContent).
Each Api Controller in myAPI is decorated with this attribute.
using myApp.Web.Common.Filters;
namespace myAPI.Web.Api.Controllers
{
[LoggingNHibernateSession]
public class CategoriesController : ApiController
{
When a Http action (Get/Post) is executed inside the ApiController, the ActionFilter gets executed and it works fine as expected.
The problem:
In the WebApplication(myContent), I have decorated those controllers as well with the ActionFilter.
using myApp.Web.Common.Filters;
namespace myContent.Web.Content.Places.Controllers
{
[LoggingNHibernateSession]
public class PlacesController : Controller
{
But here, when an action is executed inside the controller, the ActionFilter is not getting executed.
The ActionFilter belongs to System.Web.Http.Filters;
I have read some posts, and they said to use System.Web.Mvc filters. So I changed the ActionFilter to be from System.Web.Mvc
And when I switched that, the ActionFilter stopped working in WebApi as well.
What am I doing wrong here?
Although WebApi and MVC are very similar and technically consist of largely the same code, WebApi was created by copying all the code rather than through reuse. This happened, I'm told, because the WCF team didn't want a dependency on the MVC assemblies.
Therefore, code (such as your custom filter) compiled against one assembly will not work in the context of the other.
The solution is to duplicate your own code and compile against both sets of assemblies. You could also set up a build system to cross-compile the same code files using different reference assemblies.
It's truly sad when internal company politics result in something like this. The least they could do was acknowledge the problem and add some proper cross-compile support to their tooling, but alas, I digress.

Ninject dependency into AuthorizationAttribute MVC4 Web API RC

I have a custom authorization attribute, required only for some actions, which checks the request headers for a custom token. The token is checked in a database. Checking the database requires access to a service which I would like to have injected through the constructor.
The way I have read this can be done (here, here, and here) is by having a constructor-less filter and injecting the dependent one like this:
kernel.BindFilter<MyAuthorizeFilter>(FilterScope.Controller, 0).WhenControllerHas<MyAuthorizeAttribute>();
However the BindFilter method is not available to me as I have setup Ninject as described here. This is using Ninject.Web.Common instead of Ninject MVC3 as I read that Ninject MVC3 would not work with MVC4 RC. How else can I go about accomplishing this?
I have read also that I could add to GlobalFilters.Filters - however I don't want it to be present on every action.
Thanks in advance for any answers.
I'm not completely sure I see how you have set up your application, but my experience has been that if you want a filter for a WebApi controller you need to add it to the HttpFilterCollection that is available from the GlobalConfiguration.Filters. This is a Different set of filters than what MVC uses (through the GlobalFilterCollection).