Automapper WebApi middleware? - c#

I have a lot of controller methods and most of them have the same duplicating code
[Route("test"), HttpPost]
public ResponceViewModel Test(RequestViewModel model)
{
Model data = model.MapTo<Model>();
ResponceModel responce = service.DoWork(data);
return responce.MapTo<ResponceViewModel>();
}
Is it feasible to create WebApi middleware that does mapping by default. What I mean is that it checks if there is mapping between ResponceViewModel and ResponceModel and if such exists executes it. This way i will not need to write this code in every method? I will probably create some attribute to have control to stop this functionality on certain endpoints if needed. Is this good approach, if not why?

Related

ASP.NET Core ways to handle custom response/output format in Web API

I'd like to create custom JSON format, that would wrap the response in data and would return Content-Type like
vnd.myapi+json
Currently I have created like a wrapper classes that I return in my controllers but it would be nicer if that could be handled under the hood:
public class ApiResult<TValue>
{
[JsonProperty("data")]
public TValue Value { get; set; }
[JsonExtensionData]
public Dictionary<string, object> Metadata { get; } = new Dictionary<string, object>();
public ApiResult(TValue value)
{
Value = value;
}
}
[HttpGet("{id}")]
public async Task<ActionResult<ApiResult<Bike>>> GetByIdAsync(int id)
{
var bike = _dbContext.Bikes.AsNoTracking().SingleOrDefault(e => e.Id == id);
if (bike == null)
{
return NotFound();
}
return new ApiResult(bike);
}
public static class ApiResultExtensions
{
public static ApiResult<T> AddMetadata<T>(this ApiResult<T> result, string key, object value)
{
result.Metadata[key] = value;
return result;
}
}
I'd like to return response like:
{
"data": { ... },
"pagination": { ... },
"someothermetadata": { ... }
}
But the pagination would have to be added somehow to the metadata in my controller's action, of course there's some article about content negotiation here: https://learn.microsoft.com/en-us/aspnet/core/web-api/advanced/formatting?view=aspnetcore-2.1 but still I'd like to be sure I'm on the right track.
If that would be handled under the hood with my custom formatter then how would I add metadata like a pagination to it, to be aside of "data" and not inside of it?
When having a custom formatter I'd like to still have some way to add metadata to it from my controllers or by some mechanism so the format could be extensible.
One advantage or disadvantage with the approach above is that it works with all serializers xml, json, yaml etc. By having custom formatter it would probably work only for json, and I will need to create few different formatters to support all the formats that I want.
Okay, after spending some good amount of time with ASP.NET Core there are basically 4 ways I can think of to solve this. The topic itself is quite complex and broad to think of and honestly, I don't think there's a silver bullet or the best practice for this.
For custom Content-Type(let's say you want to implement application/hal+json), the official way and probably the most elegant way is to create custom output formatter. This way your actions won't know anything about the output format but you still can control the formatting behaviour inside your controllers thanks to dependency injection mechanism and scoped lifetime.
1. Custom output formatters
This is the most popular way used by OData official C# libraries and json:api framework for ASP.Net Core. Probably the best way to implement hypermedia formats.
To control your custom output formatter from a controller you either have to create your own "context" to pass data between your controllers and custom formatter and add it to DI container with scoped lifetime:
services.AddScoped<ApiContext>();
This way there will be only one instance of ApiContext per request. You can inject it to both you controllers and output formatters and pass data between them.
You can also use ActionContextAccessor and HttpContextAccessor and access your controller and action inside your custom output formatter. To access controller you have to cast ActionContextAccessor.ActionContext.ActionDescriptor to ControllerActionDescriptor. You can then generate links inside your output formatters using IUrlHelper and action names so the controller will be free from this logic.
IActionContextAccessor is optional and not added to the container by default, to use it in your project you have to add it to the IoC container.
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>()
Using services inside custom output formatter:
You can't do constructor dependency injection in a formatter class. For example, you can't get a logger by adding a logger parameter to the constructor. To access services, you have to use the context object that gets passed in to your methods.
https://learn.microsoft.com/en-us/aspnet/core/web-api/advanced/custom-formatters?view=aspnetcore-2.0#read-write
Swashbuckle support:
Swashbuckle obviously won't generate a correct response example with this approach and the approach with filters. You will probably have to create your custom document filter.
Example: How to add pagination links:
Usually paging, filtering is solved with specification pattern you will typically have some common model for the specification in your [Get] actions. You can then identify in your formatter if currently executed action is returning list of elements by it's parameter type or something else:
var specificationParameter = actionContextAccessor.ActionContext.ActionDescriptor.Parameters.SingleOrDefault(p => p.ParameterType == typeof(ISpecification<>));
if (specificationParameter != null)
{
// add pagination links or whatever
var urlHelper = new UrlHelper(actionContextAccessor.ActionContext);
var link = urlHelper.Action(new UrlActionContext()
{
Protocol = httpContext.Request.Scheme,
Host = httpContext.Request.Host.ToUriComponent(),
Values = yourspecification
})
}
Advantages (or not):
Your actions don't define the format, they know nothing about a format or how to generate links and where to put them. They know only of the result type, not the meta-data describing the result.
Re-usable, you can easily add the format to other projects without worrying how to handle it in your actions. Everything related to linking, formatting is handled under the hood. No need for any logic in your actions.
Serialization implementation is up to you, you don't have to use Newtonsoft.JSON, you can use Jil for example.
Disadvantages:
One disadvantage of this approach that it will only work with specific Content-Type. So to support XML we'd need to create another custom output formatter with Content-Type like vnd.myapi+xml instead of vnd.myapi+json.
We're not working directly with the action result
Can be more complex to implement
2. Result filters
Result filters allow us to define some kind of behaviour that will execute before our action returns. I think of it as some form of post-hook. I don't think it's the right place for wrapping our response.
They can be applied per action or globally to all actions.
Personally, I wouldn't use it for this kind of thing but use it as a supplement for the 3rd option.
Sample result filter wrapping the output:
public class ResultFilter : IResultFilter
{
public void OnResultExecuting(ResultExecutingContext context)
{
if (context.Result is ObjectResult objectResult)
{
objectResult.Value = new ApiResult { Data = objectResult.Value };
}
}
public void OnResultExecuted(ResultExecutedContext context)
{
}
}
You can put the same logic in IActionFilter and it should work as well:
public class ActionFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
}
public void OnActionExecuted(ActionExecutedContext context)
{
if (context.Result is ObjectResult objectResult)
{
objectResult.Value = new ApiResult { Data = objectResult.Value };
}
}
}
This is the easiest way to wrap your responses especially if you already have the existing project with controllers. So if you care about time, choose this one.
3. Explicitly formatting/wrapping your results in your actions
(The way I do it in my question)
This is also used here: https://github.com/nbarbettini/BeautifulRestApi/tree/master/src to implement https://github.com/ionwg/ion-doc/blob/master/index.adoc personally I think this would be better suited in custom output formatter.
This is probably the easiest way but it's also "sealing" your API to that specific format. There are advantages to this approach but there can be some disadvantages too. For example, if you wanted to change the format of your API, you can't do it easily because your actions are coupled with that specific response model, and if you have some logic on that model in your actions, for example, you're adding pagination links for next and prev. You practically have to rewrite all your actions and formatting logic to support that new format. With custom output formatter you can even support both formats depending on the Content-Type header.
Advantages:
Works with all Content-Types, the format is an integral part of your API.
Swashbuckle works out of the box, when using ActionResult<T> (2.1+), you can also add [ProducesResponseType] attribute to your actions.
Disadvantages:
You can't control the format with Content-Type header. It always remains the same for application/json and application/xml. (maybe it's advantage?)
Your actions are responsible for returning the correctly formatted response. Something like: return new ApiResponse(obj); or you can create extension method and call it like obj.ToResponse() but you always have to think about the correct response format.
Theoretically custom Content-Type like vnd.myapi+json doesn't give any benefit and implementing custom output formatter just for the name doesn't make sense as formatting is still responsibility of controller's actions.
I think this is more like a shortcut for properly handling the output format. I think following the single responsibility principle it should be the job for output formatter as the name suggests it formats the output.
4. Custom middleware
The last thing you can do is a custom middleware, you can resolve IActionResultExecutor from there and return IActionResult like you would do in your MVC controllers.
https://github.com/aspnet/Mvc/issues/7238#issuecomment-357391426
You could also resolve IActionContextAccessor to get access to MVC's action context and cast ActionDescriptor to ControllerActionDescriptor if you need to access controller info.
Docs say:
Resource filters work like middleware in that they surround the execution of everything that comes later in the pipeline. But filters differ from middleware in that they're part of MVC, which means that they have access to MVC context and constructs.
But it's not entirely true, because you can access action context and you can return action results which is part of MVC from your middleware.
If you have anything to add, share your own experiences and advantages or disadvantages feel free to comment.

User-Agent in mvc 5 application

I Have a MVC 5 application whose back-end is web API. For each request to my server I need to provide user-agent which I can get in controller action method like var UserAgent = Request.UserAgent.ToString(); and pass subsequently in other class like (Controller => Service => HttpRequester => XXXHttpClient) and finally use in actual request in XXXHttpClient class but I think there could be a better way to achieve the same. I tried to google it but didn't find anything relevant so can anyone guide me what would be the best practice If I want to get user-agent directly in XXXHttpClient class instead of passing subsequently.
Little bit of a broad question with a lot of possible answers.
Passing the data through all the layers is usually not a good thing.
What I would do is make an MVC action filter that grabs the user agent and sets it to an object. The object class could be like this:
public class RequestContext
{
public string UserAgent { get; set; }
}
Use your dependency injection framework to inject this once-per-request. Then the action filter and the layer that depends on the data would use the same instance, allowing you to get the data to any layer that needs it.
Another option which uses a static property:
HttpContext.Current.Request.UserAgent
Greater performance, easier to read, but lower testability :)

WebAPI 2 & Fluent validation - leverage RuleSet

I'm working on a Web API application, leveraging FluentValidation and AutoMapper and AutoFac. I have the basic setup, and everything is working as supposed. Validation is executed transparently for me, and in controller I can just check whether its valid or not:
[Route("")]
[HttpPost]
public HttpResponseMessage PostDinnerList(DinnerListDTO newDinnerList)
{
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
var dinnerList = _mapper.Map<DinnerList>(newDinnerList);
dinnerList.Owner.Token = _userService.GetUserToken();
dinnerList = _dinnerListRepository.InsertDinnerList(dinnerList);
var newDinnerListDto = _mapper.Map<DinnerListDTO>(dinnerList);
return Request.CreateResponse(newDinnerListDto);
}
This is OK when I pass the DTO and save it into database. However I would like to leverage the same validator with ruleset to differentiate between when new entry is created and when it's edited as different rules kick in.
I saw that in MVC version of FluentValidation, CustomizeValidatorAttribute is available, and rulesets can be selected with it. There is nothing like that in WebAPI version.
I'm thinking how can I tackle the issue. Ideally I would like to have two actions: new/update, and use the same validator and just indicate which ruleset should be used.
Workarounds that come to my mind:
On edit action use different DTO than on new action and create separate validator - but I feel like creating unnecessary/duplicated/boilerplate code.
instantiate validator in the action with the controller manually - based on a condition, indicate ruleset and invoke validation manually - but that counterfeits whole IoC setup and abstraction.
Please advise.
In case your entity for example has an auto generated Ids (identity), You can probably depend on the id of the DTO to check if your entity is new (no id set) or it is about to update (id will be set) and build your validation rules according to that using "When" or "Unless" methods.
Other option is your DTO will have a state which describe the action that you want to perform, so Added, Updated, Deleted, and Unchanged, and building the validation rules around that using "When" or "Unless" methods.
Hope this helps.

Attempting to generalize a authentication (Including parameter changing)

In our MVC project we are attempting to make everything as generic as possible.
Because of this we want to have one authentication class/method which covers all our methods.
As a example: The following code is a MVC class which can be called to from a client
public class Test
{
public void Test()
{
}
public int Test2(int i)
{
return i
}
public void Test3(string i)
{
}
}
A customer of our webservice can use a service reference to get access to Test(), Test2() and Test3().
Now i'm searching for a class, model, interface or anything else which I can use to alter the access to the method (Currently using [PrincipalPermission] attribute) as well as alter the parameter value.
Example:
Customer A calls Test2(150)
The class/method checks whether Customer A has access to Test2. The class/method validates the user but notices that the user does not have access to 150. He only has access to 100.So the class/method sets the parameter to 100 and lets it follow through on it's journey.
Customber B class Test()
The class/method checks whether Customer B has access to Test. After validation it shows that the user does not have access so it throws a SecurityException.
My question:
In what class, interface, attribute or whatever can I best do this?
(ps. As example i've only used authentication and parameter handling, but we plan to do a lot more in this stage.)
Edit
I notice most, if not all, assume I'm using actionResults. So i'd like to state that this is used in a webservice where we provide our customers with information from our database. In no way will we come in contact with a ActionResult during the requests to our webservice. (Atleast, not our customers)
Authentication can also be done through an aspect. The aspect oriented paradigm is designed to honor those so-called cross-cutting concerns. Cross-cutting concerns implemented in the "old-fashioned" oo-way make your business logic harder to read (like in Nick's example above) or even worse to understand, because they don't bring any "direct" benefit to your code:
public ActionResult YourAction(int id) {
if (!CustomerCanAccess(id)) {
return new HttpUnauthorizedResult();
}
/* the rest of your code */
}
The only thing you want here is /* the rest of your code */ and nothing more.
Stuff like logging, exception handling, caching and authorization for example could be implemented as an aspect and thus be maintained at one single point.
PostSharp is an example for an aspect-oriented C# framework. With PostSharp you could create a custom aspect and then annotate your method (like you did with the PrincipalPermissionAttribute). PostSharp will then weave your aspect code into your code during compilation. With the use of PostSharp aspects it would be possible to hook into the method invocation authenticating the calling user, changing method parameters or throw custom exceptions (See this blog post for a brief explanation how this is implemented).
There isn't a built-in attribute that handles this scenario.
I find it's usually best to just do something like this:
public ActionResult YourAction(int id) {
if (!CustomerCanAccess(id)) {
return new HttpUnauthorizedResult();
}
/* the rest of your code */
}
This is as simple as it gets and easy to extend. I think you'll find that in many cases this is all you need. It also keeps your security assertions testable. You can write a unit test that simply calls the method (without any MVC plumbing), and checks whether the caller was authorized or not.
Note that if you are using ASP.Net Forms Authentication, you may also need to add:
Response.SuppressFormsAuthenticationRedirect = true;
if you don't want your users to be redirected to the login page when they attempt to access a resource for which they are not authorized.
Here's how I've made my life simpler.
Never use simple values for action arguments. Always create a class that represents the action arguments. Even if there's only one value. I've found that I usually end up being able to re-use this class.
Make sure that all of teh properties of this class are nullable (this keeps you from running into default values (0 for integers) being automatically filles out) and thatallowable ranges are defined (this makes sure you don't worry about negative numbers)
Once you have a class that represents your arguments, throwing a validator onto a property ends up being trivial.
The thing is that you're not passing a meaningless int. It has a purpose, it could be a product number, an account number, etc. Create a class that has that as a property (e.g An AccountIdentifier class with a single field called 'id). Then all you have to do is create a [CurrentUsedCanAccessAccountId] attribute and place it on that property.
All your controller has to do is check whether or not ModelState.IsValid and you're done.
There are more elegant solutions out there, such as adding an action filter to the methods that would automatically re-direct based on whether or not the user has access to a specific value for the parameter, but this will work rather well
First, just to say it, that your own methods are probably the most appropriate place to handle input values (adjust/discard) - and with the addition of Authorize and custom filter actions you can get most done, and the 'MVC way'. You could also go the 'OO way' and have your ITest interface, dispatcher etc. (you get more compiler support - but it's more coupled). However, let's just presume that you need something more complex...
I'm also assuming that your Test is a controller - and even if it isn't it can be made part of the 'pipeline' (or by mimicking what MVC does), And with MVC in mind...
One obvious solution would be to apply filters, or action filters via
ActionFilterAttribute
Class
(like Authorize etc.) - by creating your own custom attribute and
overriding OnActionExecuting etc.
And while that is fine, it's not going to help much with parameters manipulation as you'd have to specify the code 'out of place' - or somehow inject delegates, lambda expressions for each attribute.
It is basically an interceptor of some sort that you need - which allows you to attach your own processing. I've done something similar - but this guy did a great job explaining and implementing a solution - so instead of me repeating most of that I'd suggest just to read through that.
ASP.NET MVC controller action with Interceptor pattern (by Amar, I think)
What that does is to use existing MVC mechanisms for filters - but it exposes it via a different 'interface' - and I think it's much easier dealing with inputs. Basically, what you'd do is something like...
[ActionInterceptor(InterceptionOrder.Before, typeof(TestController), "Test1")]
public void OnTest1(InterceptorParasDictionary<string, object> paras, object result)
The parameters and changes are propagated, you have a context of a sort so you can terminate further execution - or let both methods do their work etc.
What's also interesting - is the whole pattern - which is IOC of a
sort - you define the intercepting code in another class/controller
all together - so instead of 'decorating' your own Test methods -
attributes and most of the work are placed outside.
And to change your parameters you'd do something like...
// I'd create/wrap my own User and make this w/ more support interfaces etc.
if (paras.Count > 0 && Context.User...)
{
(paras["id"] as int) = 100;
}
And I'm guessing you could further change the implementation for your own case at hand.
That's just a rough design - I don't know if the code there is ready for production (it's for MVC3 but things are similar if not the same), but it's simplistic enough (when explained) and should work fine with some minor adjustments on your side.
I'm not sure if I understood your question, but it looks like a model binder can help.
Your model binder can have an interface injected that is responsible for determining if a user has permissions or not to a method, and in case it is needed it can change the value provided as a parameter.
ValueProviders, that implement the interface IValueProvider, may also be helpful in your case.
I believe the reason you haven't gotten ay good enough answer is because there are a few ambiguities in your question.
First, you say you have an MVC class that is called from a client and yet you say there are no ActionResults. So you would do well to clarify if you are using asp.net mvc framework, web api, wcf service or soap (asmx) web service.
If my assumption is right and you are using asp.net mvc framework, how are you defining web services without using action results and how does your client 'call' this service.
I am not saying it is impossible or that what you may have done is wrong, but a bit more clarity (and code) would help.
My advice if you are using asp.net mvc3 would be to design it so that you use controllers and actions to create your web service. all you would need to do would be to return Json, xml or whatever else your client expects in an action result.
If you did this, then I would suggest you implement your business logic in a class much like the one you have posted in your question. This class should have no knowledge of you authentication or access level requirements and should concentrate solely on implementing the required business logic and producing correct results.
You could then write a custom action filter for your action methods which could inspect the action parameter and determine if the caller is authenticated and authorized to actually access the method. Please see here for how to write a custom action filter.
If you think this sounds like what you want and my assumptions are correct, let me know and I will be happy to post some code to capture what I have described above.
If I have gone off on a tangent, please clarify the questions and we might be one step closer to suggesting a solution.
p.s. An AOP 'way of thinking' is what you need. PostSharp as an AOP tool is great, but I doubt there is anything postsharp will do for you here that you cannot achieve with a slightly different architecture and proper use of the features of asp.net mvc.
first create an attribute by inheriting from ActionFilterAttribute (system.web.mvc)
then override OnActionExecuting method and check if user has permission or not
this the example
public class CheckLoginAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!Membership.IslogedIn)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary
{
{ "area",""},
{ "action", "login" },
{ "controller", "user" },
{ "redirecturl",filterContext.RequestContext.HttpContext.Request.RawUrl}
});
}
}
}
and then, use this attribute for every method you need to check user permission
public class Test
{
[ChecklLogin]
public void Test()
{
}
[ChecklLogin]
public int Test2(int i)
{
return i
}
[ChecklLogin]
public void Test3(string i)
{
}
}

OnActionExecuted code for all HTTP GET actions in .NET MVC Application

What is the best way to create custom OnActionExecuted code for all HTTP GET actions in a .NET MVC application?
Would you create an ActionFilter, or create a base controller, and in either of these approaches is it possible to fire the action filter only on GET requests?
My initial thinking is a base controller written as follows, but is this the best way, or am I missing something?
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (Request.HttpMethod == "GET")
{
...
}
}
You code is good. I would use:
if (string.Equals(Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
Also if you would like to create few ActionFilters for 'GET' request only you may create common base ActionFilter class and then derive all concrete action filters from it.
Controller itself is a filter so you can use the controller or you can go for a separate class/filter. You have to analyze which one suits for you. By putting the logic in the controller you may lose unit testing so if testing/SOC are important concerns then I may suggest go for a separate class that encapsulates the logic. Also, you can avoid code duplication if you have two different base controllers in an application (rarely).
The best way to do this turned out to be neither using base controller or custom action filter declared on actions. It's best to globally register the action filter using a controller factory, and requires neither inheriting from a base controller nor adding the action filter on ever controller/action. The action filter is assigned to the Controller ActionInvoker in a custom DefaultControllerFactory derivation declared in global.asax.
This blog post was useful in implementing this approach.

Categories

Resources