What is the purpose of ASP.NET MVC Generic Controller - c#

I am newbie in asp.net mvc. I heard the word ASP.NET MVC generic controller, can anyone easily explain what it is? I have worked with the default controller before but now I want to able to visualize the kind of purpose ASP.NET MVC generic controller does. It will be very helpful if some one can explain the situations when a developer has to think about using ASP.NET MVC generic controller. Concepts and code about how to implement it will be greatly appreciated. Thanks

You usually create a generic class to abstract away operations you can perform on a range of types, for example Entity Framework models containing an ID. In that case you can move all duplicate code into a base class.
For an MVC controller, a generic base controller may look like this:
public abstract class GenericController<T>
where T : class
{
public virtual ActionResult Details(int id)
{
var model = _repository.Set<T>().Find(id);
return View(model);
}
}
And an implementation like this:
public class FooController : GenericController<Foo>
{
}
Now when someone requests /Foo/Details/42, the entitiy is pulled from the _repository's Set<Foo>(), without having to write anything for that in the FooController.
This way you can create a basic "CRUD" controller that lets you easily extend your application with Create, Read, Update and Delete operations for new models.

Related

ActionResult<TValue> in vanilla ASP.NET (non ASP.NET Core)

I'm trying to integrate Swagger into a somewhat big vanilla ASP.NET MVC app. I was going to use Swashbuckle or NSwag after reading this article. The problem is my controllers are inhereted from the generic base class like this:
public class BookController : BaseController<Book>
And then I have a GET method in a base class:
public abstract class BaseController<T> : ApiController where T : SomeEntityConstraint
{
...
public virtual IHttpActionResult Get(int id)
{
T queryResult = _repository.Get(id)
...
return Ok(queryResult);
}
}
I was planning to add [SwaggerResponse(HttpStatusCode.OK, typeof(T))] attribute to a method and this is where I got CSharp'd hard. Apparetnly one can't simply use generic type parameters in an attribute. They must be known at compile time.
I can see from here that ASP.NET Core has a neat ActionResult<TValue> class. But I can't find a substitute in a vanilla ASP.NET. I wonder what I can do in situation like this without introducing unwanted coupling and methods overriding in concrete Controller classes implementation or moving the project to a brand new ASP.NET Core.
I’m pretty sure you can implement an own ActionResult class which inherits from IHttpActionResult and just acts as proxy... i think NSwag will pick it up as if it were the ASP.NET Core one...
Disclaimer: I’m one of the devs of NSwag...

Best approach to pass database context from controller to model

I have read a lot of about IoC and design patterns but I´m not able to find clear answer. I´m doing whole data management in model, so I´m also creating database context in the model, but I found a solution from Benjamin Gale - When should I create a new DbContext(), which I like and it solves me a loft of problems with sharing db context, but my question is, how to pass this context from controller to model?
When I have ActionResult like this:
[Authorize, HttpPost]
public ActionResult AccountEditation(AccountEditationModel accountEditation)
{ ... }
Would be good solution to apply setter injection in AccountEditation actionResult, thats mean in each of actionResult method:
[Authorize, HttpPost]
public ActionResult AccountEditation(AccountEditationModel accountEditation)
{
accountEditation.db = Database; //Database from BaseController
...
}
Or is there any other way to do that?
Despite the name, ASP.NET MVC only loosely follows the MVC pattern. Namely, there's no true Model. Instead, your Model will be a combination of your entity, view models that represent that entity and your DAL, but each of these should be a separate thing. It's totally inappropriate to create or even inject a context into an entity class.
Your DAL will be the sole owner of the context. You should have an interface that represents an API that your application can use. Then, you should have one or more implementations of that interface, one per each discreet data access method (Entity Framework, Web Api, etc.). You'll then inject your context into this implementation and inject the implementation into your controller(s). The controllers, themselves, should only ever reference the interface. This is what's called the provider pattern, and it allows you sub-in different access methods as needed. Decided that you'd rather use Dapper than Entity Framework? Just create a new implementation for Dapper and inject that instead; none of the rest of your code needs to change.
The easiest thing I have found is to inject a repository into the Controller via Unity. And then pass the repository, if you need to, to whatever service or class you're using to process your business logic.
Basically...
public class AccountController : Controller
{
private IRepository<Account> _accountRepository;
public AccountController(IRepository<Account> accountRepository)
{
this._accountRepository = accountRepository;
}
}
When you use Unity and set it up properly, you can automatically inject whatever repository you're using into the AccountController class. After that, you shouldn't have a problem passing that same repository to other services or classes that need it.
Unity Dependency Injection

Generic Web API controller

I'm using Web API v2 and I have a handful of models that I need to do CRUD operations for. For example, I have an Allergy model and a Prescription model. In the application itself I have viewmodels which can turned into their appropriate models, but for simplicity's sake let's just say I take the model straight in the Web API controller.
So something like this:
public class PrescriptionsController
{
public HttpResponseMessage Put(Prescription model)
{
// saved to the DB
}
... (other CRUD operations)
}
I also have the same for the Allergy model:
public class AllergiesController
{
public HttpResponseMessage Put(Allergy model)
{
// saved to the DB
}
... (other CRUD operations)
}
Both models have different properties but are handled exactly the same way - in fact I have about 3 other models which are handled exactly the same way for each CRUD operation. I hate to do have 5 different endpoints that are basically copied and pasted code.
So my question is this:
Can I make a generic controller to handle all of these models? Something like MyCommonController<T>? (but with a better name of course!) Can the Web API handle the routing in that scenario? Is that even a good idea?
In the end I didn't try a generic controller. It seemed like it might be possible via jumping through some hoops with routing.
However, the fact that routing modifications to get this to work were so complicated it kind of negated the benefit I would get. I wanted to keep things simple. So I just created a generic base class instead:
class MyBaseController<TModel> : ApiController
{
public TModel Get(int id) { ... }
}
and had each type inherit from it:
class PrescriptionsController : MyBaseController<Prescription> { }
And that worked like charm, didn't have to mess with routing or anything. It makes it clear what's happening and is pretty maintainable.

MVC: Controller and View Communication (C#)

I am trying to build a program using model-view-controller.
Specifically:
I have a state manager that handles (initializing, loading, running, unloading etc... of) a set of MVCs, one at a time.
In each set, the single controller contains a reference to the relevant model and views.
Every model, view and controller are each derived from a parent class.
(i.e. abstract model, abstract view, abstract controller).
This allows me to keep much of the process in the parent classes, rather than adding duplicate code in each specific mvc set the state manager will handle.
Now the idea is for each View to call on its Controller methods, which in turn will call on its Model methods, and any resulting changes in the Model will be communicated back to the View through the Controller.
This is where I'm stuck. The only knowledge each view and model have of the controller is what is defined in its parent class. Which of course does not include the very specific methods the child-controller will need in order to properly handle the views and model.
Are there any ideas on how I can deal with this?
-Thanks.
You are probably closer to MVP than MVC. Anyway, getting around your problem may be possible using interfaces and generics.
Have your abstract classes take a generic interface:
public abstract class BaseView<TController>
{
protected TController Controller { get; private set; }
protected BaseView(TController controller)
{
Controller = controller;
}
}
Something to that effect.
Then your specific controller will simply implement the relevant interface.

MVC Controller Generic injection with AutoFac

I am fairly new to DI with Autofac and wonder if the following is possible
I want to create a generic controller and action that receives an
injected type.
I do not want an instance of the injected type, but just need its
type, which would be an inplementation of an expected interface.
I would also like to pass that generic type on to a ViewModel, but that is another subject altogether, however if some genious out there can solve both that would be excellent.
public ContractorController<T> : Controller
where T : IContractor{
public ViewResult New() {
var vNewModel = new NewViewModel<T>();
return View(vNewModel);
}
}
This controller should be called through
http://mysite.com/Contractor/New
I have been looking into registering generics with AutoFac, but it
seems that the problem is that the AutofacControllerFactory only implements GetControllerInstance(), expecting the controller Type passed to it from either GetController() or CreateController(), not sure which or what the diffirence is between them. These methods receive the controller's name as a string from RoutData and return the corresponding .NET type which, give the url, http://mysite.com/Contractor/New is controller=Contractor and thus ContractorController cannot be matched by GetController() or CreateController() and therfore passing null to GetControllerInstance() which mean AutofacControllerFactory does not attempt to resolve the type.
I figured that I would have to create a custom Controller Factory
deriving from AutofacControllerFactory, override GetController() or CreateController() and
perform my own mapping from the controller names to the generic types.
Something like
if (controllerName == "Contractor")
return System.Type.GetType(
"UI.Controllers." + controllerName + "Controller`1");
When I debug this I can see that this code is finding the generic controller and returning it.
I thought I could then just register the types like
builder.RegisterType<FakeContractor>().As<IContractor>();
builder.RegisterGeneric(typeof(ContractorController<>));
But I am getting the following error
The Autofac service
'UI.Controllers.ContractorController`1'
representing controller
'ContractorManagement.UI.Controllers.ContractorController`1'
in path '/Contractor/New' has not been registered.
So I think I may be barking up the wrong tree.
Can anyone please shed some light on how I can do this without pulling
my teeth
Thank you
I'm not entirely sure why you want a controller using a generic. Using a generic on a Controller isn't really supported in Mvc - or at least the supporting routing path would be involved. Perhaps you can provide more info on the reasoning behind the approach?
What it looks like is that you want a controller that supports model binding against varying types. The next question is whether these types vary across a common interface or base class.
If that's the case, for Mvc2 check out the IocModelBinder information. This will work with Autofac quite well. This will allow the type to be model bound on post or get allowing you to inject services with autofac.
If you want to vary the types by a common base - supporting a variety of concrete view model - then check out the DerivedTypeModelBinder in MvcContrib. There is a version that works in Mvc 1, 2 and now MvcContrib for Mvc3 has a good sample app to accompany it. The Mvc3 implementation is also faster - speed wasn't a problem before, it's just a more efficient identification process.
Maybe it's not a direct answer to your question, but this is the only possible way to use generic controllers that I ever seen and used:
public abstract class ContractorControllerBase<T> : Controller where T : IContractor {
public ViewResult New() {
var vNewModel = new NewViewModel<T>();
return View(vNewModel);
}
}
public class FakeContractorController : ContractorControllerBase<FakeContractor> {
}

Categories