IActionResult misunderstanding - c#

I just downloaded music store (microsoft sample projct) source code that based on ASP.NET 5. I don't understand there why developers from Microsoft use IActionResult interface as a return type in controllers.
What is a reason of IActionResult interface usage? Why don't just use ActionResult type.

See this post about IActionResult vs. ActionResult: http://forums.asp.net/post/5980446.aspx
IActionResult allows a wider range of return types, including any custom code that implements the IActionResult interface. ActionResult is limited only to those classes which extend the ActionResult abstract class (which you could also do with custom code, but using an interface allows for something like multiple inheritance, while extending a class does not).

Using interfaces as parameters will allow you to use dependency injection to obtain its dependencies and those dependencies can be replaced with mock implementations when testing which implement those interfaces.

IActionResult has more return types than ActionResult. For ex: If you want to return HttpNotFound you have to use IActionResult return type.

Related

c# HTTP Post IHttpActionResult

I have two httppost method one is taking an a concrete class with is working fine. The other one is taking in an interface. When I use postman I get null for the interface method.Should I be able to send a model class to an interface do I need to use custom model binder and if I do where do I need to add it?
public IHttpActionResult InsertData([FromBody] DataLog _datalog)
public IHttpActionResult Insert([ModelBinder(typeof(IDataLog))] IDataLog _log)
I think this would answer your question as well.
Interfaces
Reason why you cannot use interface as an object is because there are no public accessors for them. They also cannot have fields. It is just signature of the properties, and methods.
Interfaces
cannot have implementation
cannot have modifiers public
cannot have virtual
Classes
Each class you define have public properties that have getters and setters. Setters are what sets the values of these public properties. You can use the interfaces and extend them to classes and use these classes as objects to receive the data
Good read about defining and implementing interfaces
Custom Model Binding in ASP with examples
I donĀ“t know if i understand your question. Anyway regarding the code i must say:
Do not use '_' to named your variables, classes, parameters...it is not CLS compliant.
https://learn.microsoft.com/en-us/dotnet/api/system.clscompliantattribute?view=netframework-4.8
Maybe you can use the letter 'D' following the SOLID principle. D as Dependency Inversion using the IOC to Dependency Injection.
https://en.wikipedia.org/wiki/SOLIDhttps://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1
In case that you have only one return type within your method, instead of using generic ActionResults types you can do something like, just to understand the logic:
Instead of:
public ActionResult Index()
{
return View();
}
Do this:
public ViewResult Index()
{
return View();
}
Difference Between ViewResult() and ActionResult()
Do Async await (TAP ) pattern.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/
Instead of:
public IHttpActionResult InsertData([FromBody] DataLog _datalog)
Make the code to compile faster like this, adding the HttpPost attribute, even knowing this is a POST action:
Do this:
[HttpPost]
public IHttpActionResult InsertData([FromBody] DataLog _datalog)
Hope those good practices helps you somehow! :)

When to use JsonResult over ActionResult

I've been unable to find a concrete answer regarding this question. I've viewed posts and subsequent posts from this question and elsewhere but all I've really come out of reading is that JsonResult has a hardcoded content type and there really isn't any performance gains.
If both results can return Json why would you need to use JsonResult over ActionResult.
public ActionResult()
{
return Json(foo)
}
public JsonResult()
{
return Json(bar)
}
Can anyone explain a scenario where ActionResult simply can't get the job done and JsonResult must be used. If not, why does JsonResult exist in the first place.
When to use JsonResult over ActionResult
I usually return concrete results (e.g. JsonResult, ViewResult) and there are my pros:
Controller's interface gives more information about it's behavior. It is easier to work with partial or shared views when you specify PartialViewResult and ViewResult as result type precisely.
It is easier to test since it is not needed to cast result to concrete types in your unit tests.
There are some links where people support this approach:
What's the difference between ActionResult and ViewResult for action method?
Must ASP.NET MVC Controller Methods Return ActionResult?
ViewResult vs ActionResult
There is a quote from Pro ASP.NET MVC 3 Framework:
Note Notice that that the return type for the action method in the
listing is ViewResult. The method would compile and work just as well
if we had specified the more general ActionResult type. In fact, some
MVC programmers will define the result of every action method as
ActionResult, even when they know it will always return a more
specific type. We have been particularly diligent in this practice in
the examples that follow to make it clear how you can use each result
type, but we tend to be more relaxed in real projects.
I would use ActionResult over concrete one only if an action should return different types of results. But it is not that common situation.
I'd like also to add that ActionResult is an abstract class so you cannot simply create an instance of this type and return it. JsonResult is concrete so you can create its instance and return from an action method. There are many other types that derived from ActionResult and basically all of them are used to override ExecuteResult method.
public abstract class ActionResult
{
public abstract void ExecuteResult(ControllerContext context);
}
This method is invoked by ControllerActionInvoker and implements logic writing data to response object.
ControllerActionInvoker does not know about concrete results so that it can handle any result that is derived from ActionResult and implements ExecuteResult.
In both cases you return an instance of JsonResult type in your example and Json(model) it is simply a Factory Method that creates an instance of JsonResult.
There is another SO question Is it better to have a method's datatype be as specific as possible or more general? where best practices for method parameters and return values are discussed.
The general idea is providing abstract types as parameters so that your method can handle wider range of parameter; returning concrete enough types so that your clients do not need to cast or convert them.
You may have noticed that the names of all the common return types in an MVC controller end with "result", and more often than not, most actions return an ActionResult. If you look at the documentation, you can see that several, more specalized result types, inherit from the abstract class ActionResult. Because of this, you can now return an ActionResult in all of your actions, and even return different types. Example:
public ActionResult View(int id)
{
var result = _repository.Find(id);
if(result == null)
return HttpNotFound(); //HttpNotFoundResult, which inherits from HttpStatusCodeResult
return View(result); //ViewResult
}
All of this makes it easier to return different content, based on the request. So why would you use JsonResult over ActionResult? Perhaps so there are no misunderstandings, and you indeed only can return JSON, perhaps for readability, or some other personal preference.
It's just adhering simple Polymorphism principle.
By defining the method signature as returning an abstract ActionResult which is the base type for JsonResult, ViewResult, ContentResult (and others) you're given the ability to return any of the above types by letting the implementation of the action decide which ActionResult to return.
For example:
public ActionResult GetData(int id)
{
var data = .... // some data
if (Request.AcceptTypes.Contains("json"))
return Json(data);
else
return View(data);
}
It is actually a common practice in OOP to define the returned type of the method as abstract as possible. You can find it in .NET BCL as well, the IEnumerable<> usage in Linq for example:
public static IEnumerable<T> Where<T>
(
this IEnumerable<T> source,
Func<T, bool> predicate
);
The Where() method is declared as returning IEnumerable<T> so that you can call the method on any type that is implementing the IEnumerable<T> interface, be it an Array, List, HashSet or Dictionary.
Actually there is no reasons to use JsonResult as return type of Action methods.
In this case it is better to use abstract class ActionResult to follow polymorphic principles.
By calling return Json(value) you are actually calling helper method of Controller class which looks like:
protected internal virtual JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
{
return new JsonResult
{
Data = data,
ContentType = contentType,
ContentEncoding = contentEncoding,
JsonRequestBehavior = behavior
};
}
As we can see - Json helper method it instantiate JsonResult anyway.

What is the purpose of ASP.NET MVC Generic Controller

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.

Can I retrieve a ViewModel from an ActionResult?

Trying to avoid repetition here. I have an action in a base class controller which I am not allowed to modify. I'd like my action to do some checks, call the base class action, and modify the result in some way before rendering. But part of what I need to do involves modifying some properties of the ViewModel, and the base class returns an ActionResult. I see no way to get the ViewModel from the ActionResult, and so I may have to write a custom method, most of which would just mimic what the base class is doing. I'd strongly prefer not to do this. Any suggestions?
That's because ActionResult is a fairly high-level base class. Try casting it to the appropriate subtype, such as ViewResult.
Quick sample code:
public ActionResult WrapperAction()
{
// do your initial stuff
// call your base controller action and cast the result
// it would be safer to test for various result types and handle accordingly
ViewResult result = (ViewResult)base.SomeAction();
object model = result.ViewData.Model;
// do something with the model
return result;
}

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