We are using MVC3 with unobstructuve validation, all is fine; we got our custom validations working on the server as well as on the client.
We are also using the build-in asp.net Role provider. We have particular Views that we use for different Roles. Some of the fields (properties of the ViewModel) are Required based on the Role of the logged-in user.
My question is: How do we make a ValidationAttribute based on a Role? We want to make a property Required when the user is Normal User; but we don't want to make that field required when the user is an Administrator. But we do want to use the same view.
I know we can create a custom ValidationAttribute (creating a class that derives from ValidationAttribute) I suppose that will work fine for Server-Side validation. But we really want to validate this Client-Side.
I reckon we implement the IClientValidatable in our above ValidationAttribute and write some jQuery to make an Ajax call back to the server to check the current logged in user and its roles.
But this will make us do an Ajax call every time the specific property changes, and the logged-in user will not change.
What is the right way to do this? Or should we create different ViewModels for different logged in user?
Please let me know when my above explanation doesn't make sense, I can add some example code when needed.
Any help is appreciated.
Thanks,
Pim
I think you can indeed implement a custom ValidationAttribute that also implements the IClientValidatable. But then you could just "reuse" the unobtrusive required validation for the client side:
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
if ( <your condition, e.g. if user has a certain role> )
yield return new ModelClientValidationRequiredRule(<error message>);
}
This should generate the same unobtrusive required attributes on the input as the RequiredAttribute, but only if your condition is met.
Related
I cannot figure out why ASP.NET Identity does not work with my roles. I created a custom UserStore and a custom RoleStore. In my UserStore I implemented the IUserRoleStore interface, and I expected at least one of those methods to be called when ASP.NET determines if the user should be authorized to call a given endpoint, but none of the methods are getting hit.
I registered the services like this:
builder.Services.AddIdentity<User, ProReceptionRole>();
builder.Services.AddTransient<IUserStore<User>, UserStore>();
builder.Services.AddTransient<IRoleStore<ProReceptionRole>, RoleStore>();
I also tried registering the services using this variant (with and without the AddRoles part - and with different ordering of the extension methods):
builder.Services.AddIdentity<User, ProReceptionRole>()
.AddUserStore<UserStore>()
.AddRoleStore<RoleStore>()
.AddRoles<ProReceptionRole>();
When I add the [Authorize(Roles = "MyRole")] attribute to my controller class, then I get 403 Forbidden, even for users that have the given role.
I read through the documentation but I can't spot my problem. The only part that I am unsure about is that it says If you are using Roles, update the RoleManager to use your RoleStore class. - and I am assuming that this is done when I register my RoleStore, but maybe I have to do something extra?
Any pointers are greatly appreciated.
Thanks!
Where would be the best place to be able to enable/disable a filter for the entire session of the user, conditionally based on a permission?
For example I have a "CanSeeDeletedItems" permission, only for admins, and I want to apply that to everything, Ie, disable the SoftDelete filter when a request comes from a user with this permission.
I first thought to try and include this in modelBuilder, but quickly realized I cannot access the Service layer from the DAL.
So my thoughts would be to add some code to the Initializer of UOW somehow, but I am not sure how to do this, I was hoping it was a case already considered but not written into the documentation.
I'm looking to do something like this:
if (IsGranted("PermissionName"))
CurrentUnitOfWorkProvider.Current.DisableFilter(AbpDataFilters.SoftDelete);`
For user based disabling filter can be achieved with Interceptors.
So what you need to do is; Write a custom interceptor for Application Services.
This interceptor must disable/enable filter for the current execution
https://aspnetboilerplate.com/Pages/Documents/Articles/Aspect-Oriented-Programming-using-Interceptors/index.html#ArticleCreateInterceptor
To disable AspNet Boilerplate filter using in code block
using (_unitOfWorkManager.Current.DisableFilter(AbpDataFilters.SoftDelete))
{
var people2 = _personRepository.GetAllList();
}
https://aspnetboilerplate.com/Pages/Documents/Data-Filters#disable-filters
To disable AspNet Boilerplate filter globally
Configuration.UnitOfWork.OverrideFilter(AbpDataFilters.SoftDelete, false);
https://aspnetboilerplate.com/Pages/Documents/Data-Filters#disable-filters-globally
My Applicatoin is based on Spring 3, Hibernate, JSP and MySQL DB
While registering user, I want to check if username exists in DB. What is the best way to achieve this? can someone please provide example or reference to other posts?
I have tried below stuff so far
On submit of a page, I have a service call in controller which returns user object (if username exists) otherwise null. i.e. "public User userService.getUser(userName)"
I dont know how to pass the message to jsp so posting this message
I am not sure if this is the correct approach? of not please suggest
better one
I'll make a ajax call to check the existence of user by calling the this function inside the controller, and display the appropriate message if the user already exist.
public boolean isUserExist(String userName)
{
return userDao.isExist(userName);
}
Is there a built in function which will test if an email address is valid?
I want to test the email address structure is valid before sending a confirmation email to the end user.
I understand i could create my own function easy enough with the use of a regular expression but if there is a built in function i would much rather use this.
You can do this with Data Annotations extensions I believe. Check out Scott Guthrie's blog post on it here: http://weblogs.asp.net/srkirkland/archive/2011/02/23/introducing-data-annotations-extensions.aspx.
There is a good point in Scott's post as to why you would use this rather than the MVC 3 Futures validators which might be relevant to your choice:
ASP.NET MVC 3 futures defines four new data annotations attributes which this project has as well: CreditCard, Email, Url and EqualTo. Unfortunately referencing MVC 3 futures necessitates taking an dependency on MVC 3 in your model layer, which may be unadvisable in a multi-tiered project. Data Annotations Extensions keeps the server and client side libraries separate so using the project’s validation attributes don’t require you to take any additional dependencies in your model layer which still allowing for the rich client validation experience if you are using MVC 3.
Yes, you can use
public class CustomerMetaData
{
// Add type information.
[DataType(DataType.EmailAddress)]
public object EmailAddress;
}
on your model. See more about it here.
however, last time I checked it does not work client sided.
I googled it, and from imran baloch's blog post it seems it does work now.
I've read David Hayden's great post on MVC 3 Remote validation.
However there is presented what you should do to enable remote (javascript) validation. If the user has javascript disabled the post would still be made even if data is not valid. Therefore a server-side validation should occur.
How could we make this check as DRY (Don't Repeat Yourself) as possible? Of course, including the same check code in the post action as in the remote validation action (or just the same call) can work but I am wondering if a one-liner or something more elegant is available.
Perfectly acceptable answers include "no, it can't be done". :)
See my MSDN article How to: Implement Remote Validation in ASP.NET MVC
I use the remote client validation code in the HttpPost Create method to test server side when JavaScript is disabled.
[HttpPost]
public ActionResult Create(CreateUserModel model) {
// Verify user name for clients who have JavaScript disabled
if (_repository.UserExists(model.UserName)) {
ModelState.AddModelError("UserName", ValidationController.GetAltName(model.UserName, _repository));
return View("Create", model);
}
It 'can' be done.. but you would need to write your own custom attribute that basically emits for client side and is validated server side. For me I just extract the validation code into a method and check on the server.
Something similar came up recently as well:
Prevent form from submitting when using unobtrusive validation in ASP.NET MVC 3
I wonder if one couldnt inherit from the remote attribute and add their own server side code them. hmm.. maybe I'll have to try this.
I would be happy though if someone here said they already did this : )
I have done this, it's a bit of a long solution, so it's all available on my blog here:
http://www.metaltheater.com/tech/technical/fixing-the-remote-validation-attribute/
I had to create a new subclass of the RemoteAttribute class, create my own custom model binder by inheriting from DefaultModelBinder, and then use reflection to call the validator on the controller.