WebAPI 2 & Fluent validation - leverage RuleSet - c#

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.

Related

Automapper WebApi middleware?

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?

How to properly customize an Attribute for custom security in MVC 4?

In an intranet web application at my company, numerous operations have a granular, custom security system which is used in each action/http method in our MVC controllers. Basically there are two enums; one is a set of actions that can be performed (this is extremely granular; practically every possible action has a corresponding value in the enum) and one is a set of our subcompanies. For the context of this question, I will call these enums Action and Company.
Each user in our system is associated to one Company and zero or more Actions. Inside each method in our controllers, somewhere along the way there is a check for if the current user has the right Action and Company value to be using that feature. Every controller has a "UserHelper" injected into it which contains the Company and list of Actions the authenticated user is associated with.
Approaching it this way, there is a lot of code duplication in that every method is doing its own check on these enum values and reacting to violations when necessary. I am hoping to reduce this all to a System.Attribute or System.Web.Mvc.AuthorizeAttribute which we can put on controllers or methods to automatically handle violations in a uniform way and not have to check for it within the methods. Something akin to:
public class MyController : Controller
{
[RequireActionAndCompanyAttribute(Action = Action.MyMethod, Company = Company.AbcInc)]
MyMethod()
{
// do stuff, but don't bother checking for the security values
}
}
As mentioned, I am assuming I can inherit from System.Attribute or System.Web.Mvc.AuthorizeAttribute for this purpose. However, I'm struggling. I'm not sure how to adapt AuthorizeAttribute to use our own internal security implementation (based on Action and Company) rather than one of the ASP.NET Membership systems. And the plain old System.Attribute seems so vague that I'm thinking it wasn't designed for this kind of use at all. I'm also not sure how I'm supposed to pass anything to the methods in the attribute. When I put the attribute on a method, I just want to specify what Action and Company are required to continue, like in the code snippet above. But then, how do I pass the user's actual values for these into the attribute's validation method?
Use a custom attribute inherited from ActionFilterAttribute instead of the AuthorizeAttribute. You can inject your UserHelper in this class and override the OnActionExecuting method and set the Result property of the context when your condition isn't met.

Can you validate a model instance using properties from its controller?

Supposing I had, by way of demonstration, a controller that looked like this:
public class ProjectController : Controller
{
private IProjectRepository projectRepository;
public ProjectController()
{
DBContext context = new DBContext();
this.projectRepository = new ProjectRepository(context);
}
public ActionResult Create(Project project)
{
if (ModelState.IsValid)
{
// do whatever
}
else
{
return View(project);
}
}
}
And suppose that this was the controller for a model that looked like this:
public class Project : IValidatableObject
{
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
// this is where I would like to add code
}
}
My question is: is there really no way in the validation code to reference the projectRepository object on the controller? Yes, I could technically add quasi-validation to the Create() function on the controller, do the check there, and add errors directly - but in the real case, there are a number of actions that would all perform the same validation, which is really tied to the model you're trying to create (or edit, or copy, or whatever else). But it's tied to the model and to other existing instances of the same model, which only the controller knows how to query for. Is there any way to get around that?
(The goal is to check that the current model object under validation isn't the same as one that exists already; I'm open to other suggestions of how to do that as well, it just seemed like it clearly should be a job for standard validation code, either using IValidatableObject or using a ValidationAttribute. But I am not an expert in .net MVC validation, or for that matter, .net MVC at all.)
Thanks!
IValidatableObject belongs to the DataAnnotations namespace. To my mind, Data Annotations are great for input validation. Where they start to fall down is when you start applying complex business rules where your domain model's validity depends on the state of other domain models.
When that happens, introduce a service layer. Put all your business rules in there, and allow the service to mediate the conversation between your models. At the end of the day, a service is supposed to be the interface with which you communicate with your model.
This is where I usually say to myself, "Hey, your app has now reached the 'medium-complexity' stage"! :)
An older but still relevant tutorial can be found here: http://www.asp.net/mvc/tutorials/older-versions/models-(data)/validating-with-a-service-layer-cs
IMO, there is a bit of a convention issue at play. The model that the controller returns to the client is a ViewModel, not an entity. This comes into play when thinking about which objects have knowledge of dependent objects.
The repository deals with models (entities), and the controller deals with ViewModels. ViewModels are really just a bunch of data and formatting, so set-level validations don't make sense on a ViewModel.
And really want the business-layer or repository to perform set-level validation, not the model itself. You could set a reference to the repository on the model when it is created and have the model call the repository for set-level validation. But this becomes problematic when you want to clone or deserialize the entity.
By the way, EntityFramework solves these problems by allowing you to Attach a disconnected entity. You might want to use EF instead of the repository pattern.
But for you immediate issue, I would not try to perform set-level validation from within the entity or viewmodel.
You might be better of putting your validation in the service layer
The online scaffolding tool CamoteQ generate its model validation code this way, which is a good reference for self-study.

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)
{
}
}

UpdateModel without validation

Is there a possibility in ASP.NET MVC3 to set the properties of a view model from a FormCollection without invoking validation specified by validation attributes on the properties?
UpdateModel<T>(T model) also invokes validation.
The background:
I can only validate the model if a connection to the database is present, but this connection can only be established, if the data from one specific form field is correct (kind of an access code for each organisation). If the connection is not established, an exception is thrown.
When the data entered in this field is incorrect, I don't want to loose the values entered in all other form fields, but present the already entered values again to the user and give him a change to correct the errors.
So what I need is basically something like conditional validation or no validation by the model binder at all.
Is there anything like this built-in in ASP.NET MVC or do I need to write my own UpdateModel method, calling a (custom) model binder?
Why not pass the viewmodel into your method, rather than formscollection? That way you can do
[HttpPost]
public ActionResult Update(UpdateViewModel model)
{
if (!Model.IsValid)
{
return View(model);
}
}
So if the validation fails your user is going to be directed back to the Update view, with the model already populated from the information they submitted.
Now, in my opinion, having a validation attribute require a database connection, which in turn can throw exceptions is the wrong way to go about this. Those sorts of validation I move to a validation service, which is injected into the controller (and takes in the repository stuff it needs via DI as well). Each validation service will take in a view model and return a collection of ValidationResult instances, which I then attach to the model validation results via an extension method to the Controller class (both lifted from the Project Silk stuff MS P&P is pushing out)
This allows for easier testing as you can mock up the repository and have it return the correct results for testing ...

Categories

Resources