How does one configure a Remote validator via data annotations to make its call at /api/{controller} instead of /{controller}/{action}?
My model:
public class MyModel
{
[Required]
public string Name { get; set; }
[EmailAddress(ErrorMessage="We need a valid email."), Remote(....)]
public string Email { get; set; }
}
No matter what I try, the URL called by that remote validator is /foo/bar instead of just doing a get to /api/foo.
Is there any support for WebAPI in remote validators?
I'd like my email uniqueness check to use the .NET validators if at all possible (rather than having to do it manually), my form is submitted via AJAX, I'd like to validate the email prior to form submission, and using a remote validator pointing at an API controller seems like a natural choice.
Cannot use a Web API controller. This is a limitation of the RemoteAttribute. To avoid conflicts with MVC controllers, to match a Web API route you must include an httproute key, which RemoteAttribute doesn't do.
You should be able to inherit RemoteAttribute and override GetUrl to make it work.
Related
.Net Core 3.0 MVC view. Needs to apply - Client Side validation for below model.
Tried as follow:
Model:Person
public class Person {
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public int Age { get; set; }
}
Validation Rules:
public class PersonValidator : AbstractValidator<Person> {
public PersonValidator() {
RuleFor(x => x.Id).NotNull().NotEmpty();
RuleFor(x => x.Name).Length(0, 10);
RuleFor(x => x.Email).EmailAddress();
RuleFor(x => x.Age).InclusiveBetween(18, 60);
}
}
Followed documentation, it shows, "validator" attribute but I could not find in namespace.
https://docs.fluentvalidation.net/en/latest/mvc5.html
Solution 1: Use AddFluentValidationClientsideAdapters
You may use the FluentValidation.AspNetCore and register the client-side validation by adding:
services.AddFluentValidationClientsideAdapters();
Solution 2: Use FormHelper
You may also use the FormHelper and, instead of using client-side validation you could instead execute your full server-side rules via AJAX.
Details
The FluentValidation GitHub readme says:
Clientside Validation
FluentValidation is a server-library and does not provide any
client-side validation directly. However, it can provide metadata
which can be applied to the generated HTML elements for use with a
client-side framework such as jQuery Validate in the same way that
ASP.NET's default validation attributes work.
Note that not all rules defined in FluentValidation will work with
ASP.NET's client-side validation. For example, any rules defined using
a condition (with When/Unless), custom validators, or calls to Must
will not run on the client side. Nor will any rules in a RuleSet
(although this can be changed - see below). The following validators
are supported on the client:
NotNull/NotEmpty
Matches (regex)
InclusiveBetween (range)
CreditCard
Email
EqualTo (cross-property equality comparison)
MaxLength
MinLength
Length
To enable clientside integration you need to install the
FluentValidation.AspNetCore package and call the
AddFluentValidationClientsideAdapters in your application startup:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddFluentValidationClientsideAdapters();
services.AddScoped<IValidator<Person>, PersonValidator>();
// etc
}
Note that the AddFluentValidationClientsideAdapters method is only available in FluentValidation 11.1 and newer. In older versions,
you should use the AddFluentValidation method which enables both
auto-validation and clientside adapters. If you only want clientside
adapters and don't want auto validation in 11.0 and older, you can
configure this by calling services.AddFluentValidation(config => config.AutomaticValidationEnabled = false)
Alternatively, instead of using client-side validation you could
instead execute your full server-side rules via AJAX using a library
such as FormHelper. This allows you to use the full power of
FluentValidation, while still having a responsive user experience.
Specifying a RuleSet for client-side messages
If you're using rulesets alongside ASP.NET MVC, then you'll notice
that by default FluentValidation will only generate client-side error
messages for rules not part of any ruleset. You can instead specify
that FluentValidation should generate clientside rules from a
particular ruleset by attributing your controller action with a
RuleSetForClientSideMessagesAttribute:
[RuleSetForClientSideMessages("MyRuleset")]
public ActionResult Index(){ return View(new Person()); }
You can also use the SetRulesetForClientsideMessages extension method
within your controller action, which has the same affect:
public ActionResult Index()
{
ControllerContext.SetRulesetForClientsideMessages("MyRuleset");
return View(new Person());
}
You can force all rules to be used to generate client-side error
message by specifying a ruleset of "*".
Read more
Read more at:
GitHub
Documentation
Was able to figure it out.
this needs to be added under, Startup file, .AddMvc().AddFluentValidation()
So, it automatically able to pick the validation at client side as well as server side.
Thanks.
You need to add .AddFluentValidation() after .AddMvc() (or .AddControllersWithViews()) to enable Fluent Validation.
Fluent Validation supports some basic client-side validations like required, maxlength etc. If you want to use all server-side validations on client-side, you need to use third party libraries like FormHelper.
Form Helper helps you to create ajax forms and validations without writing any javascript code. It transforms server-side validations to client-side. It's very to use just add .AddFormHelper() and .UseFormHelper() on Startup.cs.
FormHelper: https://nuget.org/packages/FormHelper
Document: https://github.com/sinanbozkus/formhelper
I have a method as described below which get user as parameter.
To send the user parameter values, I am using postman request/response tool.
My question is, if the request already have user parameter in body request (see at the postman print screen ) why do I need to directly specify [FromBody] in action controller? When this attribute removed, parameter send with null values.
Thanks
[HttpPost("register")]
public IActionResult Register([FromBody]User user)
{
//.. code here
}
public class User
{
public string Name { get; set; }
public string Password { get; set; }
}
The [FromBody] directive tells the Register action to look for the User parameter in the Body of the request, rather than somewhere else, like from the URL. So, removing that confuses your method, and that's why you see null values as it's not sure where to look for the User parameters.
See: https://learn.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api for more information/learning.
For Model Binding in ASP.NET Core, MVC and Web APi uses the same model binding pattern.
There are default model bindings like Form Values, Route values and Query Strings. If these bindings fails, it will not throw an error, and return null.
If you do not want to add [FromBody], you could try Form Values binding and send request from Postman like below:
[FromBody] will override default data source and specify the model binder's data source from the request body.
You could refer Model Binding in ASP.NET Core for detail information
the attribute [FromBody] ensures the API reads the JSON payload in the postman body. For more info, read
https://learn.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api
I would like to write method validation processes which will be similar to data annontations presented in Web API.
In web api we can validate an object, for example:
public class Numbers
{
[NumberOne]
public string Number1 { get; set; }
[NumberTwo]
public string Number2 { get; set; }
}
and as long as we define the attributes NumberOneAttribute and NumberTwoAttribute its gonna be ok.
The difference is that web api has access to the GlobalConfiguration.Configuration.Filters which it seems like signalr doesn't.
Is there anyway to validate requests by attributes? or I need to follow the worst case, validate each input in the invoked method?
Thanks,
Ori.
In SignalR 2.2.x there is no native way of achieving this, but there is a project on GitHub that that adds a Validation Module in the SignalR pipeline.
Basically, in order to use it, you add a new module to the pipeline:
GlobalHost.HubPipeline.AddModule(new ValidationModule());
Then, you can use attributes like [Required] for the models' properties and then decorate the desired methods with the [Validate] attribute.
Note that this is a proof of contept project.
Best regards!
I have a Person Model
public class Person
{
public int ID { get; set; }
[Required]
[Remote("UserNameExists", "People", "Username is already taken.")]
public string Name { get; set; }
[Required]
public string LastName { get; set; }
}
This is my UserNameExists method
public JsonResult UserNameExists(string name)
{
bool exists = personRepository.GetPersonByName(name.Trim());
if (!exists)
return Json(true, JsonRequestBehavior.AllowGet);
return Json(string.Format("{0} is not avavfddvilable.", name),
JsonRequestBehavior.AllowGet);
}
When I have Javascript enabled it works just fine but when I disable javascript this rule is not enforced...
Why is this?
Please Help.
Edit for expected behavior:
According to msdn it should respect this rule even without Javacript
Optionally, disable client script in your browser, run the page again,
and enter data that violates the
validation constraints.
As you leave the field that contains
the invalid data, you do not see a
validation error because scripting is
disabled. Because ASP.NET MVC is using
unobtrusive JavaScript, you do not see
client-side script errors. However,
server-side validation is performed
when you submit the form. (It is a
good practice to test your Web
application with a browser that has
scripting disabled.)
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);
}
You must duplicate a validation call on the server - this DOES NOT work as outlined as per my testing.
See my post at:
DRY Remote Validation in ASP.NET MVC 3
It sounds like you have JavaScript disabled, and your Remote Validation fails.
Remote Validation requires JavaScript enabled in the browser. It's using jQuery and an AJAX call to get this done.
The quote from MSDN is exactly what you're observing:
you do not see a validation error
server-side validation is performed when you submit the form
Withing a Silverlight Application, how does one get the ID from the URL when using MVC given the URL in the standard MVC Format {controller}/{action}/{id}
Is there anything MVC specific or does one need to parse this URL 'manually'?
Well that's simple, either look in Request.Params["id"] or - and that's more ellegant - add a argument with the name "id" to you Controller method (case does not matter).
public void Index(string id) { }
Works even for more complex objects, the MVC does a good job in retrieving the information and matching it to the arguments of the controller method.
public class Data {
public string ID { get; set; }
}
public void Index(Data data) {
// data.id should be set
}
Silverlight runs on the client, therefore it cannot access the values on the server. However, the sever can pass the info to the client.