I am currently in the process of trying to migrate a .NET Framework 4.7 ASP MVC application over to .NET Core 3.1. I am using ASP.NET Core and found when I did the conversion I had issues with some of the custom authorization filters I was using on my methods. I want to retain the current attributes if possible, but I NEED access to the actual instance of the controller object - so I can set the value of an object inside that controller I can then access (for example, a User ID or other object) but I am unable to get the instance.
I want to decorate specific Actions with this attribute and when an incoming request comes through, perform some validation logic.
I've seen other code examples showing how via reflection I can get the controller name or type, but I need the ACTUAL INSTANCE not just the details of the object. Hope this is clear, any help is appreciated.
public class CustomAuthorizeAttribute : AuthorizeAttribute, IAsyncAuthorizationFilter
{
public async Task OnAuthorizationAsync(AuthorizationFilterContext authorizationFilterContext)
{
//How can I access the Controller instance here
//Not just the controller name, I need the actual instance
}
}
Related
What is the different between System.Web.Http.HttpPut and System.Web.Mvc.HttpPut?
Using [HttpPut] on the Web API project results the error 405 - The requested resource does not support http method 'PUT'.
They belong to two different frameworks. The pipeline flow of each is looking for specific attributes that belong to their respective namespaces.
The routing engine for the respective frameworks are not aware of the other so if a Web API attribute is used on a MVC action it would be just as if there were no attribute at all, hence the 405 error encountered.
Make sure that the correct namespace is used on the correct controller type. If both namespaces are being used in the file then be specific by calling [System.Web.Http.HttpPut] for Web API actions
[System.Web.Http.HttpPut]
public IHttpActionResult Put([FromBody]MyModel model) { return Ok(); }
and [System.Web.Mvc.HttpPut] for MVC actions
[System.Web.Mvc.HttpPut]
public ActionResult Put([FromBody]MyModel model) { return View(); }
If you are in a MVC system application you should use System.Mvc.HttpPut
It is the correct way because mvc pattern has many things that required mvc controls / methods.
Is it true that "ApiController will get deprecated in .NET Core"? Asking since I'm planning to use it in new projects.
Update ASP.NET Core 2.1
Since ASP.NET Core 2.1 a new set of types is available to create Web API controllers. You can annotate your controllers with the [ApiController] attribute which enables a few new features such as automatic model state validation and binding source parameter inference. See the docs for more information:
https://learn.microsoft.com/en-us/aspnet/core/web-api/index?view=aspnetcore-2.1#annotate-class-with-apicontrollerattribute.
There is indeed no particular ApiController class anymore since MVC and WebAPI have been merged in ASP.NET Core. However, the Controller class of MVC brings in a bunch of features you probably won't need when developing just a Web API, such as a views and model binding.
You've got two options if you want something different:
Use the ControllerBase class in the Microsoft.AspNetCore.Mvc.Core package.
Or
Create your ApiController base class. The key here is to add the [ActionContext] attribute which injects the current ActionContext instance into the property:
[Controller]
public abstract class ApiController
{
[ActionContext]
public ActionContext ActionContext { get; set; }
}
Also, add the [Controller] attribute to the class to mark it as a controller for the MVC controller discovery.
See more details in my “Web API in MVC 6” blogpost.
The [ApiController] attribute actually got added back in ASP.NET Core version 2.1.
Features coupled with the attribute are:
Validation errors automatically trigger an HTTP 400 response.
No more need to define [FromBody], [FromRoute], ... attributes explicitly
Links to the docs:
https://learn.microsoft.com/en-us/aspnet/core/aspnetcore-2.1?view=aspnetcore-2.1#apicontroller-actionresult
https://learn.microsoft.com/en-us/aspnet/core/web-api/index?view=aspnetcore-2.1#annotate-class-with-apicontrollerattribute
Update
There is also the baseclass ControllerBase for controllers to inherit from which is suited for api-controllers because it ommits all view-related functionality.
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllerbase?view=aspnetcore-2.1
In ASP.NET core uses terms and concepts known from ASP.NET MVC and ASP.NET WepAPI. But basically it is a complete new framework. Therefore there are several concepts or base classes that we can simply forget.
ASP.NET MVC and ASP.NET WebApi are two coexisting but different frameworks and therefore a destinction has to be made to specify a controller as a WebApi Controller by using the ApiController as base class.
In ASP.NET Core this is simply not necessary anymore. The Controller base class can be used for actions that return HTML from Razor Views or JSON (with output formatters XML and other formats are possible as well). You don't even need the Controller base class. It is even possible to use a "Plain Old C# Object" as Controller without inheritence.
Below is an example of a Demo-Controller to outline, that even though the ApiController is not there, the structural approach to deliver data to the client is similar.
public class DemoController : Controller
{
public async Task<IActionResult> Action()
{
var model = await _someService.GetPreciousData();
return Ok(model);
}
}
As others mentioned, ASP.NET Core is a complete new webstack that's not compatible with the old ASP.NET MVC webstack. This is explicitly reflected in it's name and versioning!
ASP.NET Core and ASP.NET Core MVC have the version 1.0.0 to make this incompatibility very clear.
ASP.NET Core merged the MVC and WebApi into one single Api just called.
And here's the thing you may have been looking for:
If you are migrating from a previous ASP.NET MVC or ASP.NET WebApi application, you may want to import the Microsoft.AspNetCore.Mvc.WebApiCompatShim package which provides some compatibility types which makes migrations easier from the previous versions. Among them is the ApiController class and certain attributes that were removed in the new webstack Api.
However, please note that this is only there to help you with migrating existing applications. When you create a new application you shouldn't use this compatibility shim and just use the new stuff.
I have two projects
Web Api
DLL Class Library
The Web Api references classes and methods in the DLL. The Web Api also uses out of the box ASP.NET Identity for security.
The Web Api controller methods are secured with [Authorize] tags as shown below:
[Authorize]
[HttpGet]
[Route("", Name = "GetStuff")]
public IHttpActionResult Get()
{
List<Stuff> Stuffs= LookUpBusinessLogic.StuffGetAll();
return Ok(Stuffs);
}
The DLL also has these tags securing its method calls as such:
[Authorize]
public static List<Stuff> StuffGetAll()
{
//Get data from somewhere
...
return Stuffs;
}
The problem I am facing is that the authorize tag is not working in the DLL method.
It is possible that I am completely missing how the calling user's identity gets passed through. I'd like to ask:
Does the calling users identity get passed between DLLs?
If not is there a way to secure the DLL methods based on the user identity in my example?
[Authorize] is an attribute which should be used only with action methods. It won't be triggered for your custom static method.
Look at its signature:
[AttributeUsageAttribute(AttributeTargets.Class|AttributeTargets.Method, Inherited = true,
AllowMultiple = true)]
public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter
Since it inherits from FilterAttribute you know it can be triggered e.g. for OnActionExecuting and OnActionExecuted methods of filter.
Your code is compiling because this attribute allows usage in methods. This doesn't mean it has any functionality when used outside controller context.
To be honest I don't understand your need of allowing DLL access for specific users. If this is some kind of class library, you should check access only in classes which are using methods from external DLL.
In our application, which is Single Page application, we are using MVC controller(Action methods as API) for CRUD operation's. Which I feel its wrong.
Can someone tell me if its correct?
Eg:-
I have an API Controller say :-
public class MockAPIController : ApiController
{
// GET api/MockAPI/5
public ClassA GetSomething(int id)
{
return new ClassA();
}
}
and this can be called from client-side using /api/MockAPI/GetSomething/1. Similarly if I create MVC Controller like:-
public class MockAPIController : Controller
{
// GET api/MockAPI/5
public ActionResult GetSomething(int id)
{
return new JsonResult(new ClassA(),JsonRequestBehavior.AllowGet);
}
}
Still, I can get it work. Can some-one tell me whats demerit of using MVC controller for API?
EDIT:-
Is it recommended to use MVC Controller for API methods?? If Not, then can someone point out the -ve aspect of it?
Using the web API you can return objects as normal and your clients can specify the content-type.
This will automatically serialize the objects to xml or json without the need to specify a new action just to change the return type.
So your API call will always remain as:
public ClassA GetSomething(int id)
{
return new ClassA();
}
But it is capable of returning xml and json without any changes in the controller.
Web API provides cleaner way to craft your HTTP responses. It is extremely extensible, testable and faithful to the HTTP spec.
Web API was NEVER intended to provide an "out-of-the-box" REST framework.
MVC is a HTTP framework, optimized for serving content to a Web Browser. Web API has no bias as to what client is using it.
As per my understanding,
MVC controllers are extended over API Controller. You can do almost
everything what can be done with API Controller.
(People please correct me if I am wrong, its purely my understanding which I am sharing!)
Now, if your application is a web based application/internet or intranet where you have very few api call's then you can stick with MVC Controllers. Only care that need to be taken care is sending data as JsonResult(basically serializing`to JSON or whatever). If you have more funda of SPA, the API controllers is what you need.
I myself have not found much articles stating a strong line separating what to use when, it's always a developers pain to decide and implement.
It's less about merit and demerit of using ApiControllers in place of Controllers, and more about implementation and usage.
ApiControllers are specifically meant for building REST-ful Apis which return serialized data to the client in simplest form.
And, using controllers you can return Views, Different Types of ActionResults in different form. You can definitely convert the type of data you are returning, like the way you are using here but it's not the same with ApiControllers.
I am creating a RESTful webservice using ASP.NET MVC (not ASP.NET Web API). What I want to do is have every method in the controller return their result based on an input parameter (i.e. json or xml).
If I were using ASP.NET Web API, the HttpResponseMessage works for this purpose. When I attempt to return an HttpResponseMessage from a controller in ASP.NET MVC, there is no detail.
I have read that in this approach, I am supposed to use ActionResult. If I do this, then I need to create an XmlResult that inherits from ActionResult since it is not supported.
My question is why HttpResponseMessage does not work the same in both situations. I understand that in Web API, we inherit from ApiController and in ASP.NET MVC we inherit from System.Web.Mvc.Controller.
Any help is greatly appreciated.
Thanks,
EDIT 1
Much thanks to Fals for his input. My problem was in how to create an empty website and add all of the necessary functionality in. The solution was to use Nuget to get the packages mentioned in the comments and then to follow the steps in How to integrate asp.net mvc to Web Site Project.
Web Api is a Framework to develop Restfull services, based on HTTP. This framework was separeted into another assembly System.Web.Http, so you can host it everywhere, not only in IIS. Web API works directly with HTTP Request / Response, then every controller inherit from IHttpController.
Getting Started with ASP.NET Web API
MVC has It's implementation on System.Web.Mvc. coupled with the ASP.NET Framework, then you must use It inside an Web Application. Every MVC controller inherits from IController that makes an abstraction layer between you and the real HttpRequest.
You can still access the request using HttpContext.Response directly in your MVC controller, or as you said, inheriting a new ActionResult to do the job, for example:
public class NotFoundActionResult : ActionResult
{
private string _viewName;
public NotFoundActionResult()
{
}
public NotFoundActionResult(string viewName)
{
_viewName = viewName;
}
public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.StatusCode = 404;
context.HttpContext.Response.TrySkipIisCustomErrors = true;
new ViewResult { ViewName = string.IsNullOrEmpty(_viewName) ? "Error" : _viewName}.ExecuteResult(context);
}
}
This ActionResult has the meaning of respond thought HTTP Error.
As a matter of fact, it is indeed possible. You basically have two options:
develop your custom ActionResult types, which can be an heavy-lifting work and also quite hard to mantain.
add WebAPI support to your website.
I suggest you to do the latter, so you will have the best of two worlds. To do that, you should do the following:
Install the following Web API packages using NuGet: Microsoft.AspNet.WebApi.Core and Microsoft.AspNet.WebApi.WebHost.
Add one or more ApiControllers to your /Controllers/ folder.
Add a WebApiConfig.cs file to your /App_Config/ folder where you can define your Web API routing scheme and also register that class within Global.asax.cs (or Startup.cs) file.
The whole procedure is fully explained here: the various steps, together with their pros-cons and various alternatives you can take depending on your specific scenario, are documented in this post on my blog.