Could someone provide a good tutorial on how may I validate my html fields with unobtrusive,
but without using MVC helpers.
Is it possible at all?
I would like to keep the plain html and use input type="text" field instead of mvc helpers <%= Html.TextBox("Name") %> but still using the model validation..
public class Employee
{
[Required]
public string Name { get; set; }
}
Also is it possible with jquery Ajax?
Thanks
While it is possible to perform unobtrusive validation in MVC without using helpers, it will be painfully for you as developer to do it manually without usage of mvc helpers. Saying strictly, it will kill your performance and make your code unreadable.
Basically, unobtrusive validation consists of two parts: server side, via data-attributes to your model fields and MVC Helpers, which generate necessary markup, and client side library, jquery.validate.unobtrusive.js, which parses those markup to meaningful parts for jquery validate plugin.
So, in general, you can manually write necessary markup, as long as validation js library will be loaded, validation will work. For example, field, which is subject of validation, must be marked with data-val='true' attribute. If you want to make your field required, you should write additionally something like data-val-required="error message". For length validation - data-val-length-min="5" (obviously, minimum) data-val-length-max="50" (maximum length), data-val-length="Min 5 max 50 chars required".
While, when using normal mvc approach, it is just a question of model attribute:
[Required]
[StringLength(50, MinimumLength = 5)]
public string Name { get; set; }
and one line of code in markup:
#Html.TextBoxFor(o=>o.Name)
Nice, shiny, separates View and Model, and helps KISS.
And for second part of your question. If I understood your problem correctly, you want to validate dynamic forms. Probably it will be answer:
jquery.validate.unobtrusive not working with dynamic injected elements
Related
This is the sample ViewModel I get to the view:
public class CollectionOfStuffVM
{
public string Element { get; set; }
public bool IsPicked { get; set; }
}
This is asking for a Checkbox for multiple items, or a dropdown list if it is a single pick only.
But, what if I am drawing this in a custom way?
Eg. below (inside a editor template):
#Model.Element
All the "data-picked" stuff is being handled by javascript when something is clicked.
So, how would it be possible to automatically bind these custom "controls"?
I guess there's some work that needs to be done, i'm just not sure, where. Do I need to create a custom Input?
I know this auto bind would be doable with inputs, but i'm kinda avoding having to have hidden inputs being updated by Javascript.
Keep in mind this is just a simple example, the ViewModel is a bit more complex and it would be frustrating to have to build everything in Javascript to do an Ajax POST.
There's no such thing as two-way databinding when it comes to MVC. This is because, unlike something like a WPF application where everything runs on the same machine, a web application is disjointed, with server-side and client-side components.
If you want the data set by the client to be set back on the server, you have to post it to the server. If you handle that with a standard form, you must include some kind of input that has that value. If you do it with AJAX, you have a bit more freedom, as you don't need a physical HTML input element to hold the value, but you're still responsible for ensuring that the value makes it into the object you send to the server via AJAX.
I am looking for best practices for design razor view with MVC.
which would be better option:
HtmlHelper extension methods
#Html.TextBox("txtName")
or
write the html directly
<input type"text" id="txtName" name="txtName" />
I found 2 diferent links.
The first one http://blogs.msdn.com/b/aspnetue/archive/2010/09/17/second_2d00_post.aspx says DO use HTMLHelper extension methods.
and the second one http://codeclimber.net.nz/archive/2009/10/27/12-asp.net-mvc-best-practices.aspx says 10 – Write HTML each time you can
so i am a little cofused
Even the name HtmlHelper should already give you a hint whether you should use it or not. Do you want help? If not, just write html from the scratch. It does not really matter how the html was generated: from the scratch or using html helper. What matter is that it was generated with correct names of the inputs so that model binder can bind these inputs to the model.
For example, suppose you have the following Model that will be passed to the view and that will be received on the POST:
public class SomeModel
{
public Customer Customer { get; set; }
}
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
In order to make sure that your inputs will be binded to the model you need three inputs on your page:
<input type="hidden" id="whatever" name="Customer.Id" />
<input type="text" id="whatever" name="Customer.FirstName" />
<input type="text" id="whatever" name="Customer.LastName" />
Having this html markup will assure proper model minding. However, you can achieve this markup by using HtmlHelpers, which is a lot easier:
#Html.HiddenFor(m => m.Customer.Id)
#Html.TextBoxFor(m => m.Customer.FirstName)
#Html.TextBoxFor(m => m.Customer.LastName)
This will not only give you proper name attributes on every input, but also assign id attributes accordingly so you don't have to do that all by your self.
It appears that the author from the second article suggests to never use HtmlHelpers for two reasons:
the learning purposes: I assume by saying "web developers have to be
comfortable writing HTML" he means that developer should know
exactly what html markup is required for proper model binding.
the fear of black box: It seem that author is afraid that improper html
markup will be generated by using HtmlHelpers or he just does not
know what html will be generated.
I disagree with his phrase: "HtmlHelpers whose only reason of living is hiding the HTML away". I'd rather say "HtmlHelpers whose only reason of living is helping writing Html markup"
Summary:
HtmlHelpers help you write proper html markup, which is why I suggest you using it.
Since you're using Razor, I would make the most of what it has to offer, and the HtmlHelper extensions allow you to write html quicker and easier in a lot of places.
There may be times when you have to use Html instead, where you might want to include tags in an anchor and cannot use #Html.ActionLink, for example.
But where you can achieve the same result with either approach, I'd recommend you go with Razor.
Html helpers are not cosmetic code snippets that just save time. Consider choosing the appropriate editor based on model property types, and - what is also very important - they help in client validation, provided you include jquery.unobtrusive-ajax.js and jquery.validate.js.
The last cannot be achieved by simply writing HTML.
From what I said it can be easily derived that Html helpers "know" about the model, while plain markup does not.
At the end it is up to you to decide what to use, but knowing more about Html helpers is better when making a decision.
I'm using ASP.NET MVC 3 + FLUENT VALIDATION + NINJECT
I have model X and rules for that model are something like this:
RuleFor(c => c.FirstName).NotEmpty();
RuleFor(c => c.LastName).NotEmpty();
I spotted a little strange thing, the engine puts validation attributes on all hidden elements and on dropdowns, radio buttons, etc.., and I didn't specified this in the validation configuration for that model, so I guess it is by default...
<input type="hidden" value="1" name="Id" id="Id" data-val-required="'Id' must not be empty." data-val-number="The field Id must be a number." data-val="true">
Validation works because hidden element always have a value, but I have a problem with radio buttons. For example, if I don't want one radio button always to be selected by default but empty and if I want to put validation rules on that item, the rendering puts default validation attributes and on top of my rules, so it's getting messed up and validation doesn't work properly...
Anyone had similar issues or knows about this, or do I have to pull the ASP.NET MVC source and look it up by myself? :)
Semi-Lazy and little-pushed-down-by-deadlines coder
Edit:
I tried proposed solution from this link:
Fluent Validations. Error: Validation type names in unobtrusive client validation rules must be unique
but asp.net mvc emits required attributes on each field regardless of AddImplicitRequiredAttribute settings...
Make the Id property on your view model a nullable integer.
So instead of:
public int Id { get; set; }
you should use:
public int? Id { get; set; }
Same stands true for any other value types that you don't want to be required. You should use nullable types.
Html helpers automatically emit data-val attributes for all non-nullable types which is by design and if you do not want this behavior you will have to write your own custom HTML helpers to generate your input fields and dropdowns. You can no longer rely on TextBoxFor and DropDownListFor helpers as that's how they are designed.
I'm stuck with ASP.NET MVC 3 jQuery unobtrusive validation message localisation. Specifically with "number" validation. If I have a number property in model input html is rendered with data-val-number attribute with value "The field Quantity must be a number." How I can localize this string. With data annotation attributes there is no problem to define localized message. But for number validation I do not have to specify any attribute.
So, how can be localized validation messages generated by unobtrusive validation?
I got to solution refering this article http://jwwishart.wordpress.com/2010/03/22/custom-server-and-client-side-required-validator-in-mvc-2-using-jquery-validate/
It works, but still very unconvenient.
If there is only one culture it could be convenient to use
$('input[data-val-number]').attr('data-val-number', 'Custom message');
This script must go before
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
Found something. This blog explains step by step how to accomplish this. I just tried a quick run through using MVC 3 unobstructed validation and it worked perfect.
Basically, you add a resource, and use validation attribute like this:
[Range(1, 130, ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "Range")]
public string myNumber { get; set; }
The result was client validation with my custom string.
Let's say you have simple object like this :
public class MyObject {
public int Test { get; set; }
}
And you count on the default model binder to make sure the user does not leave the "Test" field empty when posting a form like below :
<form method="post" action="/test">
<p>
<%=Html.TextBox("Test") %>
<%=Html.ValidationMessage("Test") %>
</p>
<input id="Submit1" type="submit" value="submit" />
</form>
And this action :
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Test(MyObject o) {
return View();
}
This all works as expected when the form data contains a key for "Test" (like "Test=val" or "Test=")
But if the key is not in the form data, then the validation doesn't occur. So in case of an empty post request or a request with a data like AnotherField=foo the property on the model object defaults to the type's default value (in this case 0). And ModelState.IsValid returns true.
This is, IMO, not the behaviour one would expect.
So what do you suggest to change this behaviour?
Edit :
Keep in mind that a malicious user can just tamper the form data easily with FireBug or Tamper Data plugin to pass the default model binder's validations, which could cause some security problems.
It is not validating the fields by design, unfortunately. Please take a look at this Codeplex issue that I've found and commented on.
It is really unfortunate, that MS has decided this is the correct behaviour for their model binder.
I believe the default model binder should validate the whole entity instead of just the posted data.
You might consider using xVal to perform the necessary mix of client- and server-side validation. With it, you can add an attribute to your Test property dictating what sort of validation rules (required, regex validation, etc.) apply to it and then, with a little more work, get it to generate JavaScript rules for you as well as pretty easily perform model validation.
You're already aware that you're violating a rule of development - never trust client input. There's really no way around it.
Client-side validation (preventing a round trip to find out that there's an error) is nice-to-have, server-side validation verifying that things truly are in order is a must-have.
i hope its by design because I am about to start relying on this behavior!
in one instance i have two controls which post back the following fields :
ShippingAddress.FirstName
ShippingAddress.LastName
ShippingAddress.Line1
ShippingAddress.Line2
BillingAddress.Email
BillingAddress.FirstName
BillingAddress.LastName
BillingAddress.Line1
BillingAddress.Line2
Note: Billing Address does not have email displayed, even though the underlying model of course still has it
If I have Email as a [Required] data annotation in my model then it will only complain when it is missing from Billing Address.
But I definitely see your point! I'm just relying on it for this one scenario here!
After researching all the different ways to get the form values into my controller methods, I discovered that the "safest" was to explicitly define each form field as a parameter to the controller. A side effect is that if a form does NOT have one of the fields, it will throw an exception - which would solve your problem.