What kinds of controllers should I consider for extensibility in ASP.NET MVC 4 application - vb.net

I am using System.Web.Mvc.Controller for the UI and System.Web.Http.ApiController for the API in prototyping a web interface for large ERP application. I have figured out a way to make the UI somewhat extensible with the question Deploying un-compiled ASP.NET MVC Razor application. Now I am wondering, due to the strict nature of ApiController if there is some other class I should be considering for providing an open-ended interface for defining custom API transactions. Or is there some way to use ApiController in a more open-ended way where parameter count and type may be varied... perhaps by accepting an object parameter?

For Web API, you could try implementing a custom action selector using IHttpActionSelector interface:
public class CustomActionSelector : IHttpActionSelector
{
public override HttpActionDescriptor SelectAction(HttpControllerContext context)
{
var method = GetMethod(context);
return new ReflectedHttpActionDescriptor(GetController(method), method);
}
private MethodInfo GetMethod(HttpControllerContext context)
{
// Locate the target method using the extensibility framework of your choice
// (for example, MEF, pure reflection, etc.)
}
private HttpControllerDescriptor GetController(MethodInfo method)
{
return new HttpControllerDescriptor()
{
ControllerName = method.DeclaringType.Name,
ControllerType = method.DeclaringType
};
}
}
To register your new action selector place the following in your global.asax file under Application_Start:
var config = GlobalConfiguration.Configuration;
config.Services.Replace(typeof(IHttpActionSelector), new CustomActionSelector());
Hope this helps.

To make an ASP.NET web application extensible is very straightforward because ASP.NET searches the bin directory for controller classes in all assemblies there. So if the party providing customizations can simply compile their code into a DLL and drop it into the bin directory, your web application will pick up all their controllers as well as the controllers from the standard delivery. As an example, I created the following class in a standalone DLL that referenced System.Web.Http and System.Web.Mvc:
Public Class CustomTestController
Inherits ApiController
Public Function GetValues() As IEnumerable(Of String)
Return New String() {"value1", "value2"}
End Function
End Class
I simply compiled it and copied it to the bin directory of the location where my web application was deployed, and then I could access http://localhost/MyApplication/api/CustomTest/ and get back value1 and value2 in the expected response.

Related

.Net Core : Class Library to connect to DB, DAL, User Secret and Asp.Net Core's Configuration

I have the following :
a class library with connection classes such as connection, command, parameter
a DAL with entities, mapper, interface, services as well as a static class that holds hard coded connectionString and InvariantName.
an Asp.Net Core project
References :
DAL has a reference to the class library to make use of its connection class to which it provides connectionString and InvariantName thanks to its static class etc..
Asp.Net has a reference to the DAL.
What I want :
I now want to use the User Secrets to store hard coded sensitive data connections and get rid off the static class.
I know I can use the the Asp.Net Core startup.cs to read the settings from Configuration and make use of binding to store them into a class and use DI.
My guess :
DI seems "easy" when used inside an Asp controller. But I need the settings values (connectionString and InvariantName) outside the Asp.Net Core to be injected into a constructor of a class somewhere in my DAL.
I guess I would then need to have to reference the Asp.Net Core project to my DAL. But then I would end up with a circular reference (DAL to Asp.Net Core and the opposite).
So what's the solution?
Have an intermediate library class into which I would retreive the settings values from Asp.Net Core and then pass them to my DAL (to prevent circular reference)?
Manually recreate the "Configuration process" inside the DAL and get settings there directly
Or something else that I don't know?
Ps : I am new in development and only have a few projects'experience in Asp.Net Framework so far..and it's my first Asp.Net Core project
I know I can use the the Asp.Net Core startup.cs to read the settings from Configuration and make use of binding to store them into a class and use DI
You already answered your own question with this. This is the correct and recommended behavior to setup DI for 3rd party libs and configurations. If you want to avoid clutter in Startup class, create an extension method:
namespace Microsoft.Extensions.DependencyInjetion
{
public static MyLibraryCollectionExtensions
{
public static IServiceCollection AddMyLibrary(this IServiceCollection services)
{
services.AddDbContext<MyDbContext>(...);
}
}
}
to register your classes. Alternatively, extend the method to accept a parameter delegate to configure it
namespace Microsoft.Extensions.DependencyInjetion
{
public static MyLibraryCollectionExtensions
{
public static IServiceCollection AddMyLibrary(this IServiceCollection services, Action<MyOptions> setup)
{
var defaultOptions = ... // i.e. new MyOptions();
// pass default options to be modified by the delegate
setup?.Invoke(defaultOptions);
// your registrations
services.AddDbContext<MyDbContext>(...);
}
}
}
And all the user has to do in your library is add
services.AddMyLibrary();
// or with setup
services.AddMyLibrary(config =>
{
config.MyConnectionString = Configuration.GetConnectionString("MyContext");
});
and store the connection string in the appsettings.json.
{
"ConnectionStrings":
{
"MyContext" : "MyConnectionString here"
}
}
I finally used the ConfigurationBuilder to get values from the appsettings.json file.
It's probably not the right way to do it but it is working with my DAL and Connection dlls.
In case it helps anyone else :

How to resolve dependency inside AuthorizeAttribute with WebApi and Ninject

My current setup is using Ninject for simple IoC, everything goes fine, but I'm not able to resolve one of the classes I need inside my AuthorizeAttribute. I need to access a class that does ClaimsVerification:
Here's my code:
IoC Config:
var kernel = new StandardKernel(); // Ninject IoC
// These registrations are "per instance request".
// See http://blog.bobcravens.com/2010/03/ninject-life-cycle-management-or-scoping/
kernel.Bind<RepositoryFactories>().To<RepositoryFactories>()
.InSingletonScope();
kernel.Bind<IRepositoryProvider>().To<RepositoryProvider>();
kernel.Bind<ISmartDocumentorUow>().To<SmartDocumentorUow>();
kernel.Bind<IClaimsVerification>().To<ClaimsVerification>();
// kernel
//kernel.BindFilter<MyAuthorizeAttribute>(FilterScope.Controller, 0).WhenControllerHas<RequireRolesAttribute>();
// Tell WebApi how to use our Ninject IoC
config.DependencyResolver = new NinjectDependencyResolver(kernel);
MyAuthorizeAttribute:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
[Inject]
IClaimsVerification clamisverify { get; set; }
public MyAuthorizeAttribute()
{
//var x = System.Web.Mvc.DependencyResolver.Current.(typeof(IClaimsVerification));
}
Yap, sorry, the problem was injecting the iClaimsverification that isn't working in web api..
I tryed with the public property and still it didn't work.
the bindfilter is commented out, because it doesn't exist in the core NInject api (dll), it does exists in the MVC dll of ninject but it works for Action filters in the web mvc, and not in the api mvc for what i can tell..
i do solved the issue like this, though i don't like a lot of this fix:
private IClaimsVerification verifier
{
get
{
return (GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IClaimsVerification)) as IClaimsVerification);
}
}
The property you have marked with Inject is private - you need to initialize Ninject with a custom configuration to opt into what would be a much less efficient process
(You didnt state the problem in your question. I see you were trying BindFilter, but it's commented out (why?) - this is the correct approach. I recommend reading the Ninject.MVC3 wiki article on BindFilter for an example)

How to share fluent configuration in a Castle Windsor IOC container

I am trying to create an IOC container in Castle Windsor that's configuration is shared across assemblies.
(What follows is an example of how this works in Unity. What I want to do is to make it work the same way using Castle Windsor)
I have the following project configuration...
TestCompany.Services.Host
(Web project hosting a number of .svc files)
PrintService.svc
Web.Config
Unity.Config
TestCompany.Services.PrintService
IPrintService.cs
PrintService.cs
The actual implementation of my "PrintService" is not implemented inside my Services.Host but in the TestCompany.Services.PrintService assembly.
As part of my shared project code (not shown) I have a container helper which is responsible for loading the unity configuration...
public static IUnityContainer GetContainer()
{
// Checks for existance of container (_container == null) ommitted.
var section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
section.Configure(_container, name);
...
...
}
This method loads the unity configuration section from the Unity.Config and uses it to configure the container.
The advantage of this method is that one Unity.Config loaded inside (I presume) the AppDomain can service a number of assemblies. Simply calling GetContainer() from any of the assemblies consumed by my service host will return a container populated with the same type resolution's etc.
I really want to use the fluent configuration in Castle Windsor but I dont see how without this "shared" configuration file that can be acheived. PrintService and any future services will all need to resolve the same dependencies and I dont want to have to repeat my fluent configuration between these services.
Ideally I need some sort of container configured in the service host app that can "flow" into all of the assemblies that it makes use of.
Thanks.
I think I may not be understanding your question but I think I understand your scenario and here is how I do something similar, if it helps at all...
My Philosophy:
Each part of the application should be in charge of registering what
it knows about and nothing more, so there is no need for a single
central configuration file and things that are shared between
components are registered in one place and their interfaces are
available everywhere via a common library.
So let's take an example...
First of all, let us just say (for the purposes of my example) that IPrintService is something that you want to register an implementation of once and use throughout the application and that we have some other component that needs to be implemented by some external module from the main application. We, therefore, create an assembly called Common like so:
Common
public interface IPrintService
{
void Print();
}
public interface IMyService
{
void DoSomething();
}
Now let us think about the main part of the application (maybe it is an ASP .NET application, maybe justa console application, does not really matter). Here we construct the container and ask it to find all the possible components. We can do that like so:
Main Application
// Could be the Global.asax code behind but for simplicity this is
// just a console application
class Program
{
private static readonly IWindsorContainer Mycontainer
= BootstrapContainer();
// Allow access to the raw container - this is probably a bad idea but
// in the rare case that you need it you can get it from here
public static IWindsorContainer Container { get { return Mycontainer; } }
private static IWindsorContainer BootstrapContainer()
{
// Here we will just install every IWindsorInstaller found in any
// assembly in the same folder as the application (so no need for
// references or anything).
var c = new WindsorContainer();
string folder = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location);
c.Install(FromAssembly.InDirectory(new AssemblyFilter(folder)));
return c;
}
}
// Here is the print service implementation
public class MyPrintService : IPrintService
{
public void Print()
{
// Print!
}
}
// This is the installer for the main module - here we are saying exactly
// what is implementing the interface
public class MainApplicationInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container,
IConfigurationStore store)
{
container
.Register(Component
.For<IPrintService>()
.ImplementedBy<MyPrintService>());
}
}
So now we have a common library with our shared inetrfaces and a main application that will register an implementation for our shared interface and also load up any other modules in the system.
The only thing, therefore, left to do is to consume that print service and use it. We can do this anywhere that is using the container so let's create a third assembly that references only Common (we will call it test module.
Test Module
// This installer installs just the things inside this module since that
// is all it knows about but those things can use things that are
// registered in the container by anybody.
public class TestModuleInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container,
IConfigurationStore store)
{
container
.Register(Component
.For<IMyService>()
.ImplementedBy<MyServiceThatDoesSomething>());
}
}
public class MyServiceThatDoesSomething : IMyService
{
private readonly IPrintService _printService;
public MyServiceThatDoesSomething(IPrintService printService)
{
_printService = printService;
}
public void DoSomething()
{
// Use the print service!
_printService.Print();
}
}
Finally compile everything and copy the test module to the same folder as the main application and then from the main you can do this:
Container.Resolve<IMyService>().DoSomething();
And then the magic happens! Well, some code runs and you find that the print service is called by the class from the module even though it knows nothing about it.
Anyway, maybe that helps a little bit, maybe not, good luck!

How to add global ASP.Net Web Api Filters?

I've created a Web Api filter (using System.Web.Http.Filters.ActionFilterAttribute) but I am unable to get it to work inside of ASP.Net MVC 4. I tried adding it to the RegisterGlobalFilters() method but that didn't work.
So if one is using Web Api hosted in ASP.Net MVC how does one register filters?
The following code, in my Global.asax, works for me:
public static void RegisterWebApiFilters(System.Web.Http.Filters.HttpFilterCollection filters)
{
filters.Add(new MyWebApiFilter());
}
protected void Application_Start()
{
RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters);
}
note that this answer holds true up to MVC 5/Web API 2
Short answer: MVC and Web API filters are not cross compatible, and if you want to register them globally, you must use the appropriate configuration classes for each.
Long answer: ASP.NET MVC and Web API are purposely designed to work in a similar way, but they are in fact different creatures.
Web API lives under the System.Web.Http namespace, whereas MVC lives under the System.Web.Mvc namespace. The two will happily live side by side, but one does not contain the other and despite the similarities in the programming model, the underlying implementations are different. Just as MVC controllers and Web API controllers inherit different base controller classes (MVC's is simply named Controller and Web API's is named ApiController) MVC filters and Web API filters inherit from different FilterAttribute classes (both share the same name in this case, but are separate classes which live in their respective namespaces).
Web API global filters are registered through the HttpConfiguration object available to you in the Register method WebApiConfig.cs if you're using a project template with WebActivator:
public static void Register(HttpConfiguration config)
{
//stuff before
config.Filters.Add(new MyWebApiFilter());
//stuff after
}
or otherwise in the global.asax.cs:
GlobalConfiguration.Configuration.Filters.Add(new MyWebApiFilter());
Mvc global filters are registered by way of a GlobalFilterCollection object, which is available to you through the RegisterGlobalFilters method of FilterConfig.cs for projects that are using WebActivator:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//stuff before
filters.Add(new MyMvcFilter());
//stuff after
}
}
or in the global.asax.cs file by way of GlobalFilters.Filters collection for those without WebActivator:
GlobalFilters.Filters.Add(new MyMvcFilter());
It's worth noting that in both cases you do not need to inherit from the appropriate FilterAttribute type. Web API Filters need only implement the System.Web.Http.IFilter interface, while MVC filter registration checks to ensure that your class inherits one of a handful of filter interfaces defined in the System.Web.Mvc namespace.
As of MVC 4 RC, the correct class name is HttpFilterCollection:
public static void RegisterWebApiFilters(System.Web.Http.Filters.HttpFilterCollection filters)
{
filters.Add(new MyWebApiFilter());
}
protected void Application_Start()
{
RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters);
}
Instead of using global filters I prefer to do this :
[MyWebApiFilter]
public class CustomizedApiControllerBase : ApiController
{
...
}
And after that inherit all of api controllers from CustomizedApiControllerBase
This approach is more expressive in comparison with global filters in global.ascx file.

Ninject, Linq to Sql, request scope for each controller without injecting

I recently came across this article titled:
Linq to Sql and ASP.NET MVC – DataContext Per Request
at this link:
http://www.jeremyskinner.co.uk/2010/01/31/linq-to-sql-and-asp-net-mvc-datacontext-per-request/
I would like to set this up using ninject rather than structuremap preferably using the new mvc 3 dependency resolver as I'm using mvc 3 rtm.
The relevant part of the article is this:
Firstly, you’ll need to configure StructureMap by calling ObjectFactory.Configure inside your Global.asax passing in a custom Registry instance:
protected void Application_Start() {
RegisterRoutes(RouteTable.Routes);
ObjectFactory.Configure(cfg => {
cfg.AddRegistry(new MyRegistry());
});
}
The code for MyRegistry looks like this:
public class MyRegistry : Registry {
public MyRegistry() {
For<BlogDataContext>()
.HttpContextScoped()
.Use(c => new BlogDataContext());
Scan(scan => {
scan.AddAllTypesOf<Controller>();
});
}
}
Here I’m telling StructureMap to create one instance of my BlogDataContext per HTTP Request as well as registering each Controller instance with the container.
Next, we need to tell MVC to use StructureMap to instantiate our controllers. This can be done by creating a custom ControllerFactory:
public class StructureMapControllerFactory : DefaultControllerFactory {
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) {
return (IController) ObjectFactory.GetInstance(controllerType);
}
}
We can then replace the DefaultControllerFactory with the StructureMapControllerFactory in our Application_Start:
protected void Application_Start() {
RegisterRoutes(RouteTable.Routes);
ObjectFactory.Configure(cfg => {
cfg.AddRegistry(new MyRegistry());
});
ControllerBuilder.Current.SetControllerFactory(
new StructureMapControllerFactory());
}
I would like to do the same thing with ninject 2.0 rather than structure map. I'm building an mvc 3 site with ninject mvc3. I downloaded the ninject mvc 3 package from nuget and I have this file in my solution which handles wiring up ninject.
AppStart_NinjectMVC3.cs
I do not want to use structurmap and I know the same setup can be done with ninject, but I'm unsure how to wire it up.
Thank you.
I'd rather use the official mvc3 extension from the ninject project found at https://github.com/ninject/ninject.web.mvc. It comes with a full example application showing how to wire up an mvc3 application.