MVC4 many types of validation - asp.net-mvc

i have this view
#using (Html.BeginForm("RegisterApartmentOwner", "Home", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="editor-label">
#Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
#Html.TextBoxFor(x => x.FirstName, new {placeholder = "Enter Your First Name" })
#Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.LastName, new { placeholder = "Enter Your Last Name"})
#Html.ValidationMessageFor(model => model.LastName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Password)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Password, new { placeholder = "Enter Your Password"})
#Html.ValidationMessageFor(model => model.Password)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Password)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Password, new { placeholder = "Enter Your Password Again"})
#Html.ValidationMessageFor(model => model.Password)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.MobileNumber)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.MobileNumber, new { placeholder = "Enter Your Mobile Number"})
#Html.ValidationMessageFor(model => model.MobileNumber)
</div>
<input type="submit" value="Register" class="submit"/>
}
my problem is that the validation works just when the fields are empty, but i want the validation to discover when the two passwords are not equal, and when the mobilenumber is not numbers and so on. what should i do please?

You should take a look at data annotations http://msdn.microsoft.com/en-us/library/dd901590(v=vs.95).aspx

You could try the jQuery.Validation.Unobtrusive.Native nuget package. It's really easy to implement and will fit your needs.
Installation
Just add to you web.config file
<appSettings>
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
and in your Visual Studio go to Tools -> Library Package Manager -> Package Manager Console
Now in the console type
PM> Install-Package jQuery.Validation.Unobtrusive.Native.MVC4
After you installed the package you should check out the demo site or download the
source from github for more information
jQuery.Validation.Unobtrusive.Native Package
jQuery.Validation.Unobtrusive.Native.Demo Site
Using NuGet Package Manager
And in your case look at this Examples:
EqualTo
Demo Validation
Best regards

you can use the Data Annotations Extensions library it is available as nuget pagkage
Here is the site http://dataannotationsextensions.org/
Nuget package http://www.nuget.org/packages/DataAnnotationsExtensions
Demos http://dataannotationsextensions.org/Home/Demos

For the model you have created you can use data annotations and as per #kkern if u have enabled unobtrusive validation enabled and included all js file reference you can validate them by simply adding attributes in your properties. A Sample includes as following:
public class MyModel
{
[Required(ErrorMessage="First Name is Required")]
public string FirstName {get; set;}
[Required(ErrorMessage="")]
public string Password {get; set;}
[Compare("Password")]
public string ConfirmPassword {get; set;}
[RegularExpression(#"^[0-9]{7,13}$", ErrorMessage = "Contact No must be digits only and length of 7-13.")]
public string MobileNo {get; set;}
}

ASP.NET MVC has some validation attributes like RegularExpression or DataType but they are not enough for some situations. In that case you need a mask for your textbox and the best one is meio. The site provides you lots of examples for different cases.
To check the equality of two passwords you need to write some javascript code or add a new rule in Jquery validation. Comparing two passwords with Jquery might be helpful. The Compare attribute is another choice to compare two values.

Use could use in your model a self-validating approach:
public class TestModel : IValidatableObject
{
public string FirstName { get; set; }
public string Password { get; set; }
public string PasswordConfirm { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (FirstName == null)
{
yield return new ValidationResult("FirstName is mandatory.");
}
if (Password != PasswordConfirm)
{
yield return new ValidationResult("Password confirmation does not match.");
}
}
}
In your controller you would have something like this:
[HttpPost]
public ActionResult Create(Model model) {
if (!ModelState.IsValid) {
var errors = model.Validate(new ValidationContext(model, null, null));
foreach (var error in errors)
{
foreach (var memberName in error.MemberNames)
{
ModelState.AddModelError(memberName, error.ErrorMessage);
}
}
return View(model);
}
}
More info about this approach: How to force MVC to Validate IValidatableObject

Related

What could be causing for ASP.NET MVC form to not properly submit/deserialize?

This looks like it should be working, yet the form submits with model not properly deserialized. Using latest ASP.NET MVC from nuget. .NET 4.5
A very standard user-registration View/Controller.
View:
#model Alertera.Portal.Web.Models.RegisterViewModel
#{
ViewBag.Title = "Register";
}
<h2>#ViewBag.Title.</h2>
#using (Html.BeginForm("Register", "Account", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Create a new account.</h4>
<hr />
#*#Html.ValidationSummary()*#
<div class="form-group">
#Html.LabelFor(m => m.UserName, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.UserName, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.FirstName, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.FirstName, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.LastName, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.LastName, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Password, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.ConfirmPassword, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.ConfirmPassword, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Register" />
</div>
</div>
}
Controller:
// POST: /Account/Register
[AcceptVerbs(HttpVerbs.Post)]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new User
{
UserName = model.UserName,
FirstName = model.FirstName,
LastName = model.LastName
};
user.SetEmail(model.Email);
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
_bus.Publish(new UserCreated(user));
await SignInAsync(user, isPersistent: false);
return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
All of the posts are coming in with model being empty or forgery token not present (depends if I enable or disable verficiation). I'm simply stumped and don't know where to look.
** EDIT **
If I disable antiforgery, ModelState is invalid, all of the fields in the model are empty and error messages state that fields are required.
I'm using Autofac with MVC extensions and Model binder is registered like so:
builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
builder.RegisterModelBinderProvider();
Autofac is working in general, as controller is instantiated properly and is injected with propery dependencies.
Edit 2:
Created a custom binder by inheriting from the DefaultModelBinder, per suggestion, so that I could see the transformation. It looks like the bindingContenxt's model is null
The view model itself is here:
public class RegisterViewModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string FirstName { get; set; }
}
After a full day of trubleshooting, updating all of the nuget packages, making sure that web.config's are all tight and contain proper assembly redirects, routes are neat, and even repair of .NET framework and other time consuming and irrelevant activities, I've finally figured this out:
A few weeks prior, we've introduced an Autofac binding that would capture serialized HttpContext along with other relevant data for when the logging framework would need it. (Imagine being able to log request information alongside a full exception stack inside a business object without polluting business logic with session/logging data.)
Unfortunately, as a part of the binding creation, the HttpContext was being serialized by Json.net and not at the time of the logging of the event, but at the time of the binding.
Apparently, when Json.net seralizes HttpContext, it actually reads the streams inside it for the first time, causing the submitted form data to be read, so that when Controller is instantiated and data for it is posted, the streams have already been read and Request.Form colection is empty.
Simple fix to only create a delegate to serialize HttpContext appears to have fixed the issue

ASP.Net MVC 4.0 - Validation Issues With array based properties on ViewModel

ASP.Net MVC 4.0 - Validation Issues With array based properties on ViewModel .
Scenario :
When a ViewModel has a string array as a property type,the default Scaffolding template for say, Edit, does not render the that property in the markup.
Say, I have ViewModel setup like this :
Employee.cs
public class Employee
{
[Required]
public int EmpID
{
get;
set;
}
[Required]
public string FirstName
{
get;
set;
}
[Required]
public string LastName
{
get;
set;
}
[Required]
public string[] Skills
{
get;
set;
}
}
}
The (strongly typed) Edit View generated by the scaffolding template, as shown below, typically skips the portion relevant to field Skills.
**Employee.cshtml**
#model StringArray.Models.Employee
#{
ViewBag.Title = "EditEmployee";
}
<h2>EditEmployee</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Employee</legend>
<div class="editor-label">
#Html.LabelFor(model => model.EmpID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.EmpID)
#Html.ValidationMessageFor(model => model.EmpID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LastName)
#Html.ValidationMessageFor(model => model.LastName)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
The corresponding Controller code is
..
[HttpGet]
public ActionResult EditEmployee()
{
Employee E = new Employee()
{
EmpID = 1,
FirstName = "Sandy",
LastName = "Peterson",
Skills = new string[] { "Technology", "Management", "Sports" }
};
return View(E);
}
[HttpPost]
public ActionResult EditEmployee(Employee E)
{
return View(E);
}
To get the missing section for the Skills field, I added
Snippet to the View
<div class="editor-label">
#Html.LabelFor(model => model.Skills)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Skills)
#Html.ValidationMessageFor(model => model.Skills)
</div>
Corresponding UIHint to the ViewModel
[UIHint("String[]")]
public string[] Skills ...
EditorTemplates inside relevant folder as
~\View\shared\EditorTemplates\String[].cshtml
and
~\View\shared\EditorTemplates\mystring.cshtml
string[].cshtml
#model System.String[]
#if(Model != null && Model.Any())
{
for (int i = 0; i < Model.Length; i++)
{
#Html.EditorFor(model => model[i], "mystring")
//Html.ValidationMessageFor(model => model[i])
}
}
mystring.cshtml
#model System.String
#{
//if(Model != null)
{
//To resolve issue/bug with extra dot getting rendered in the name - like
//Skills.[0], Skills.[1], etc.
//ViewData.TemplateInfo.HtmlFieldPrefix=ViewData.TemplateInfo.HtmlFieldPrefix.Replace(".[", "[");
#Html.TextBoxFor(model => model)
}
}
But despite this all, the Validations for the Skills section [with 3 fields/elements - refer the EditEmployee method in Controller above.]
are entirely skipped, on postback.
I tried below changes inside the mystring.cshtml EditorTemplate :
//to correct the rendered names in the browser from Skills.[0] to Skills for all the 3 items in the
//Skills (string array), so that model binding works correctly.
string x = ViewData.TemplateInfo.HtmlFieldPrefix;
x = x.Substring(0, x.LastIndexOf("."));
#Html.TextBoxFor(model =>model, new { Name = x })
Postback WORKS But Validations DON'T, since the "data-valmsg-for" still points to <span class="field-validation-valid" data-valmsg-for="Skills" data-valmsg-replace="true"></span>
and thus doesn't apply at granular level - string element level.
Lastly, I tried removing #Html.ValidationMessageFor(model => model.Skills) from the Employee.cshtml and correspondingly adding the
same to string[].cshtml as #Html.ValidationMessageFor(model => model[i]).
But this led to data-valmsg-for getting rendered for each granular string element like
data-valmsg-for="Skills.[0]" ,
data-valmsg-for="Skills.[1]" and data-valmsg-for="Skills.[2]", respectively.
Note: Validations work for other fields - EmpID, FirstName LastName, BUT NOT for Skills.
Question
How do I set the data-valmsg-for="Skills" for each of the above three granular elements related to Skills property.
I am stuck on this for quite some time now. It would be nice if some one can point out the issue, at the earliest.
Thanks, Sandesh L
This is where you like to change
[Required]
public string[] Skills
{
get;
set;
}
You are giving validation on the array.
you might want to have a new string class call Skill
[Required]
public string Skill
{
get;
set;
}
And you can change to you model with
[Required]
public List<Skill> Skills
{
get;
set;
}
I prefer using List instead of array. Then, you can change you skill view according to the model updated
you template view can be something like
#model IEnumerable<Skill>
<div class="editor-label">
<h3>#Html.LabelFor(model=> model.Skills)
</h3>
</div>
<div class="editor-field">
#foreach (var item in Model)
{ #Html.Label(model => item)
#Html.TextBoxFor(model => item) <br/>
}
#Html.ValidationMessageFor(model => item)

How to turn off MVC form validation

I have a data-first set-up so my models are generated by the entity framework from my database and there is no default [Required] annotations. I have a simple table with three fields. One ID and two VARCHAR / text based fields.
No matter what I try, I cannot get the CRUD forms to stop validation. I disabled in the Web.config, I add [ValidateInput(false)] to the Create() method in the controller, but has no effect. I set the #Html.ValidationSummary to false,
This is the basic view:
#using (Html.BeginForm()) {
#Html.ValidationSummary(false)
<fieldset>
<legend>CallType</legend>
<div class="editor-label">
#Html.LabelFor(model => model.CALLTYPE)
</div>
<div class="editor-field">
#Html.TextBox("calltype", "", new { style = "width: 50px;" })
#Html.ValidationMessageFor(model => model.CALLTYPE)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DESCRIPTION)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.DESCRIPTION)
#Html.ValidationMessageFor(model => model.DESCRIPTION)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
Model (generated by Framework):
public partial class CALLTYPES2
{
public int ID { get; set; }
public string CALLTYPE { get; set; }
public string DESCRIPTION { get; set; }
}
Even if I insert just one character in each field, it still says: "The Value 'x' is invalid"
(I leave the validation messages on so I can see what is going on.)
What am I supposed to do? And how would I validate these fields later on - can I just add [Required] to Model generated code? What if I regenerate the Model from the database?
Does this have something to do with the model state in the controller?
[HttpPost]
public ActionResult Create(CALLTYPES2 calltype)
{
if (ModelState.IsValid)
{
db.CALLTYPES2.Add(calltype);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(calltype);
}
Not sure what I am missing and the tutorials I have read do not shed much light. Thanks for your response and apologies for my ignorance.
UPDATE
Found my error - The object name "calltype" in the Method Create() is the same as the name/id of the form field "calltype". I guess the binder tries to bind the string "calltype" to the object "calltype". Renamed it to:
public ActionResult Create(CALLTYPES2 ctype)
Now it works in both the Edit and Create Windows. "ctype" is not clashing with "calltype".
You forgot to include the ID field in your form. You could include it as a hidden field:
#Html.HiddenFor(model => model.ID)
Now the value of the ID property will be sent to the server when the form is submitted and the default model binder should not complain.

Passing an object as an error message in validation

I want to know, is there a way that I can pass an object(let's say a Message instance) from the validation in the model's fields and retrieve them from the ModelState( or by using some other thing) instance. Why I'm asking this is, I want to differentiate between the validation error message types so I can display only the messages I want in the view at a time. (Ex : required messages shown before the unique validation messages.)
I was trying to use a custom created Message object which I can then distinguish using its messageType field. But as the validation only returns string messages, can't think of a way.
Are you ok with reading the messages out of ModelState and determining type based on message content? That can be done if you set a custom message for all the validations.
Then you can evaluate each message looking for specific content and take action. Such as putting the word "Error" in the Required attribute and Info in the rest.
Here's a class you can use to test
Model
public class EmployeeViewModel {
public int ID { get; set; }
[Display(Name = "First Name")]
[Required(ErrorMessage = "Error")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
[Required(ErrorMessage = "Error")]
public string LastName { get; set; }
[Display(Name = "Username")]
public string Username { get; set; }
[Display(Name = "Email Address")]
public string EmailAddress { get; set; }
}
Controller
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using TestApp.Models;
namespace TestApp.Controllers {
public class HomeController : Controller {
public ActionResult Index() {
return RedirectToAction("Test");
}
public ActionResult Test() {
var model = new EmployeeViewModel();
return View(model);
}
[HttpPost]
public ActionResult Test(EmployeeViewModel model) {
// Force an error on this property - THIS should be the only real error that gets returned back to the view
ModelState.AddModelError("", "Error on First Name");
if(model.EmailAddress == null) // Add an INFO message
ModelState.AddModelError("", "Email Address Info");
if (model.Username == null) // Add another INFO message
ModelState.AddModelError("", "Username Info");
// Get the Real error off the ModelState
var errors = GetRealErrors(ModelState);
// clear out anything that the ModelState currently has in it's Errors collection
foreach (var modelValue in ModelState.Values) {
modelValue.Errors.Clear();
}
// Add the real errors back on to the ModelState
foreach (var realError in errors) {
ModelState.AddModelError("", realError.ErrorMessage);
}
return View(model);
}
private IEnumerable<ModelError> GetRealErrors(IEnumerable<KeyValuePair<string, ModelState>> modelStateDictionary) {
var errorMessages = new List<ModelError>() ;
foreach (var keyValuePair in modelStateDictionary.Where(keyValuePair => keyValuePair.Value.Errors.Count > 0)) {
errorMessages.AddRange(keyValuePair.Value.Errors.Where(error => !error.ErrorMessage.Contains("Info")));
}
return errorMessages;
}
}
}
private IEnumerable<ModelError> GetRealErrors(IEnumerable<KeyValuePair<string, ModelState>> modelStateDictionary) {
var errorMessages = new List<ModelError>() ;
foreach (var keyValuePair in modelStateDictionary.Where(keyValuePair => keyValuePair.Value.Errors.Count > 0)) {
errorMessages.AddRange(keyValuePair.Value.Errors.Where(error => !error.ErrorMessage.Contains("Info")));
}
return errorMessages;
}
View
#model TestApp.Models.EmployeeViewModel
<h2>Test</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>EmployeeViewModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LastName)
#Html.ValidationMessageFor(model => model.LastName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Username)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Username)
#Html.ValidationMessageFor(model => model.Username)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.EmailAddress)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.EmailAddress)
#Html.ValidationMessageFor(model => model.EmailAddress)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>

ASP.NET MVC Model Binder Fails with Strings that look like version numbers?

This should be straight-forward, but here goes - we're using MVC4 to handle a multi-part Form request to upload a binary along with some meta-data via a strongly-typed view in MVC4.
One of the fields is a version number for the file (i.e. something like 0.0.6, 0.4.5-pre, etc...)
I'm getting the following error from the model binder when it tries to bind this version number field to the model field (string type):
{"The parameter conversion from type 'System.String' to type
'Models.NewFileVersion' failed because no type converter can convert
between these types."}
Specifically the error can be traced to our "VersionNumber" field - any ideas as to why this might be happening?
Edit: Source code below
NewFileVersion.cs
public class NewFileVersion
{
[Display(Name = "Version # (0.67, 0.66-pre, etc...)")]
[Required]
public string Version { get; set; }
[Required]
[StringLength(2000, ErrorMessage = "ChangeLog must be between 30 an 2000 characters", MinimumLength = 30)]
[Display(Name = "Version Notes (will be visible to end-users)")]
[DataType(DataType.MultilineText)]
public string ChangeLog { get; set; }
[Display(Name = "Target Platform")]
[UIHint("Enum")]
public FileType PlatformTarget { get; set; }
}
New.cshtml
#model ViewModels.NewFileVersion
#{
ViewBag.Title = "New";
}
<div class="container" id="main-content">
<div class="row">
<h2>
New</h2>
#using (Html.BeginForm("Create", "Files", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>NewFileVersion</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Version)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Version)
#Html.ValidationMessageFor(model => model.Version)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ChangeLog)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ChangeLog)
#Html.ValidationMessageFor(model => model.ChangeLog)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PlatformTarget)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PlatformTarget)
</div>
<div class="editor-label">
<label for="">
File:</label></div>
<div class="editor-field">
<input type="file" name="fileData" required="required" /></div>
<p>
<input type="submit" value="Upload File" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
</div>
</div>
FilesController.cs
[HttpPost]
public ActionResult Create(NewFileVersion version, HttpPostedFileBase fileData)
{
//if our model is valid
if(ModelState.IsValid)
{
//etc....
}
ModelState.AddModelError("", "Invalid file submission");
return View("New", version);
}
Try renaming the version parameter for your Create action, e.g:
public ActionResult Create(NewFileVersion fileVersion, HttpPostedFileBase fileData) { ... }
The model binder may be getting confused between the string version model property and the NewFileVersion version action parameter.
You can see why this happens in the BindModel method, because the model has a property exactly matching the name of the action parameter it tries to bind as a simple type/model rather than a complex one.

Resources