Model.IsValid always returning true - validation

Ok I am near wits end here. I've got a simple MVC3 application with a viewmodel
ViewModel
public class TicketViewModel {
public Ticket Ticket { get; set; }
[DisplayName("Name")]
[Required(ErrorMessage = "Requestor's name is required.")]
public string Name { get; set; } }
Controller
[HttpPost]
public ActionResult Create(TicketViewModel vm)
{
if(ModelState.IsValid) {
TempData["message"] = "Your ticket has been submitted.";
TempData["message-class"] = "success";
return RedirectToAction("Index");
}
TempData["message-class"] = "error";
return View("Index", vm);
}
For some reason ModelState.IsValid is coming through as true all the time. Even when Name is left blank. It's like the model/viewmodel isn't validating at all. This works on other applications so I'm pretty sure I'm not hooking up something. I've got all the validation javascript included as well though I don't think that's the problem right now.
Update
Interestingly enough, the html tags that are being generated by #Html.TextBoxFor() are NOT including the data-val and data-val-required attributes.
View
#model MyApp.ViewModels.TicketViewModel
#{
ViewBag.Title = "Tickets";
}
<div id="main-content">
<section class="large">
<div class="section">
<div class="section-header">Submit Ticket</div>
<div class="section-content">
<div class="message"></div>
#using( Html.BeginForm("Create", "Home", FormMethod.Post) ) {
<h2>User Information</h2>
<dl>
<dt>#Html.LabelFor( m => m.Name)</dt>
<dd>
#Html.TextBoxFor( m => m.Name)
#Html.ValidationMessageFor( m => m.Name)
</dd>
<dt></dt>
<dd><button>Submit</button></dd>
</dl>
}
</div>
</div>
</section>
</div>
UPDATE II
Well now this is interesting. I created a fresh app and got things working with basic code. Then when I added DI code to the global.asax.cs validations stopped working. Specifically, when I add
public void SetupDependencyInjection() {
_kernel = new StandardKernel();
RegisterServices(_kernel);
DependencyResolver.SetResolver(new NinjectDependencyResolver(_kernel));
}
and call it from Application_Start()
protected void Application_Start()
{
SetupDependencyInjection();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
if I remove SetupDependencyInjection() validations start working. To be clear, DI works well but it seems to kill validations. This worked well prior to MVC3 Tools Update.

I was able to find a solution. Seems that when you install Ninject via nuget the configuration is a little different. It configures your application from the App_Start folder. Basically I was doubling up on my Ninject-Fu calling in from global.asax. This ended up causing the weird validation issues, though the other parts of the application were working.
Ninject - Setting up an MVC3 application

Are you perhaps using something other that the default model binder (with the DI)? I'm pretty sure that the default model binder will validate an object upon binding. If you are not using the default one, you may not experience the same behavior.

Try using
#Html.EditorFor(model => model.Name)
That should apply the data- attributes correctly

I got the same error using Ninject.Mvc together with DependencyResolver. The reason was that I created a new IKernel instance for each Bootstrapper and DependencyResolver object.
//Application_Start()
DependencyResolver.SetResolver(new NinjectDependencyResolver(NinjectBooster.CreateKernel()));
To solve the problem I've changed the code to use the same cached instance, like this:
//Application_Start()
DependencyResolver.SetResolver(new NinjectDependencyResolver(NinjectBooster.GetKernel()));
...
//NinjectMVC.cs
private static IKernel _kernel;
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
public static IKernel GetKernel()
{
if (null == _kernel)
{
_kernel = new StandardKernel();
RegisterServices(_kernel);
}
return _kernel;
}

Related

how do I build a composite UI in MVC3?

I understand how to use Partial Views, and I understand Ajax.ActionLink and Ajax.BeginForm when it comes to how to set those up in the view. I'm assuming each partial view has it's own controller. I'm thinking bounded context here, as in each partial view could talk to it's own bounded context via its own controller
I guess the piece I'm missing is:
how to have partial views included in a "master view" (or holding view) and have each of these partial views independently post to a separate controller action, and then return to refresh the partial view WITHOUT loading the "master view" or holding view.
the "master" view or holding view still needs to have its own controller, I want to keep the master controller from reloading its view, and let the view that is produced by an action method of the master controller hold a reference to these two partial views.
There are two approaches it seems I can take, one is to use the "Ajax." functionality of MVC3, the other is to use straight-up jQuery and handle all this interaction by hand from the client side.
Is what I'm trying to do possible both ways, or is one way "better suited" to this type of composite ui construction?
So far, the only things I have seen are trivial examples of composite ui construction like a link via an Ajax.ActionLink that refreshes a single on the page, or a form written as an Ajax.BeginForm that repopulates a div with some content from a partial view.
Okay, so I finally have some working code that I think is the right way to do it. Here is what I went with. I have a two simple "entities"; Customer and BillingCustomer. They're really meant to be in separate "bounded contexts", and the classes are super-simple for demostration purposes.
public class Customer
{
public Guid CustomerId { get; set; }
public string Name { get; set; }
}
public class BillingCustomer
{
public Guid CustomerId { get; set; }
public bool IsOverdueForPayment { get; set; }
}
Note that both classes reference CustomerId, which for the sake of this demo, is a GUID.
I started with a simple HomeController that builds a ViewModel that will be utilized by the Index.cshtml file:
public ActionResult Index()
{
var customer = new Customer {
CustomerId = Guid.Empty,
Name = "Mike McCarthy" };
var billingCustomer = new BillingCustomer {
CustomerId = Guid.Empty,
IsOverdueForPayment = true };
var compositeViewModel = new CompositeViewModel {
Customer = customer,
BillingCustomer = billingCustomer };
return View(compositeViewModel);
}
The CompositeViewModel class is just a dumb DTO with a property for each domain entity, since the partial views I'll be calling into in my Index.cshtml file each need to pass their respective domain model into the partial view:
public class CompositeViewModel
{
public BillingCustomer BillingCustomer { get; set; }
public Customer Customer { get; set; }
}
Here is my resulting Index.cshtml file that uses the Index method on the HomeController
#model CompositeViews.ViewModels.CompositeViewModel
<h2>Index - #DateTime.Now.ToString()</h2>
<div id="customerDiv">
#{Html.RenderPartial("_Customer", Model.Customer);}
</div>
<p></p>
<div id="billingCustomerDiv">
#Html.Partial("_BillingCustomer", Model.BillingCustomer)
</div>
A couple things to note here:
the View is using the CompositeViews.ViewModels.CompositeViewModel ViewModel
Html.RenderPartial is used to render the partial view for each
entity, and passes in the appropriate entity. Careful with the
syntax here for the Html.Partial call!
So, here is the _Customer partial view:
#model CompositeViews.Models.Customer
#using (Ajax.BeginForm("Edit", "Customer", new AjaxOptions {
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "customerDiv" }))
{
<fieldset>
<legend>Customer</legend>
#Html.HiddenFor(model => model.CustomerId)
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
the important part here is the Ajax.BeginForm call. Note that it's explicitly calling the Edit ActionMethod of the CustomerController. Also note that the UpdateTargetId is set to "customerDiv". This div is NOT in the partial view, but rather in the "parent" view, Index.cshtml.
Below is the _BillingCustomer view
#model CompositeViews.Models.BillingCustomer
#using (Ajax.BeginForm("Edit", "BillingCustomer", new AjaxOptions {
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "billingCustomerDiv" }))
{
<fieldset>
<legend>BillingCustomer</legend>
#Html.HiddenFor(model => model.CustomerId)
<div class="editor-label">
#Html.LabelFor(model => model.IsOverdueForPayment)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.IsOverdueForPayment)
#Html.ValidationMessageFor(model => model.IsOverdueForPayment)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
Again, note that UpdateTargetId is set to billingCustomerDiv. This div is located in the Index.cshtml file, not this partial view file.
So, the only thing we haven't looked at yet is the Edit ActionResult on the CustomerController and the BillingCustomerController. Here is the CustomerController
public class CustomerController : Controller
{
[HttpGet]
public PartialViewResult Edit(Guid customerId)
{
var model = new Customer {
CustomerId = Guid.Empty,
Name = "Mike McCarthy"};
return PartialView("_Customer", model);
}
[HttpPost]
public ActionResult Edit(Customer customer)
{
return PartialView("_Customer", customer);
}
}
There is nothing really "happening" in this controller, as the post deals directly with building a composite UI. Notice how we're returning via "PartialView" and specifying the name of the partial view to use, and the required model the view needs to render.
Here is BillingCustomerController
public class BillingCustomerController : Controller
{
[HttpGet]
public PartialViewResult Edit(Guid customerId)
{
var model = new BillingCustomer {
CustomerId = Guid.Empty,
IsOverdueForPayment = true };
return PartialView("_BillingCustomer", model);
}
[HttpPost]
public PartialViewResult Edit(BillingCustomer billingCustomer)
{
return PartialView("_BillingCustomer", billingCustomer);
}
}
Again, the same as CustomerController, except for the fact that it's this controller is dealing with the BillingCustomer entity.
Now when I load up my HomeController's Index ActionResult, I get a screen that looks like this:
Each Save button will do an async postback to the controller the partial view needs to update and talk to in order to get data, all without causing a regular postback for the whole page. You can see the DateTime stamp does NOT change when hitting either save button.
So, that's how I went about building my first composite view using partial views. Since I'm still very new to MVC3, I could still be screwing something up, or doing something in a way that is harder than it needs to be, but this is how I got it working.

MVC3 Custom Validation error message doesn't display when using ViewModel

SUMMARY
Question: Why doesn't the custom validation error message show when using a ViewModel.
Answer: The custom validation should be applied to the ViewModel not the Class. See the end of #JaySilk84's answer for example code.
MVC3, project using
jquery-1.7.2.min.js
modernizr-2.5.3.js
jquery-ui-1.8.22.custom.min.js (generated by jQuery.com for the Accordion plugin)
jquery.validate.min.js and
jquery.validate.unobtrusive.min.js
I have validation working in my project for both dataannotations in the View and for ModelState.AddModelError in the Controller so I know I have all the validation code configured properly.
But with custom validation an error is generated in the code but the error message doesn't display.
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{ if (DOB > DateTime.Now.AddYears(-18))
{ yield return new ValidationResult("Must be 18 or over."); } }
Drilling down in debug in the POST action the custom validation causes Model state to fail and the error message is placed in the proper value field but when the model is sent back to the view the error message doesn't display. In the controller I also have ModelState.AddModelError code and its message does display. How is that handled differently as to one would work and not the other? If not that what else would prevent the error message from displaying?
Update 1 :
I'm using a ViewModel to create the model in the view. I stripped out the ViewModel and the error message started displaying, as soon I added the ViewModel back in the message again stopped displaying. Has anyone successfully used a custom validation with a ViewModel? Was there anything you had to do extra to get it to work?
Update 2 :
I created a new MVC3 project with these two simple classes (Agency and Person).
public class Agency : IValidatableObject
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime DOB { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (DOB > DateTime.Now.AddYears(-18)) { yield return new ValidationResult("Must be over 18."); }
}
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
Here's the Controller Code
public ActionResult Create()
{
return View();
}
//
// POST: /Agency/Create
[HttpPost]
public ActionResult Create(Agency agency)
{
if (ModelState.IsValid)
{
db.Agencies.Add(agency);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(agency);
}
//[HttpPost]
//public ActionResult Create(AgencyVM agencyVM)
//{
// if (ModelState.IsValid)
// {
// var agency = agencyVM.Agency;
// db.Agencies.Add(agency);
// db.SaveChanges();
// return RedirectToAction("Index");
// }
// return View(agencyVM);
//}
The View
#model CustValTest.Models.Agency
#*#model CustValTest.Models.AgencyVM*#
#* When using VM (model => model.Name) becomes (model => model.Agency.Name) etc. *#
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Agency</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DOB)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.DOB)
#Html.ValidationMessageFor(model => model.DOB)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
The ViewModel
public class AgencyVM
{
public Agency Agency { get; set; }
public Person Person { get; set; }
}
When just Agency is presented in the View the validation error displays (DOB under 18). When the ViewModel is presented the error doesn't display. The custom validation always catches the error though and causes ModelState.IsValid to fail and the view to be re-presented. Can anyone replicate this? Any ideas on why and how to fix?
Update 3 :
As a temporary work around I have changed the Validation into a field level one (vs. a model level one) by adding a parameter to the ValidationResult:
if (DOB > DateTime.Now.AddYears(-18)) { yield return new ValidationResult("Must be over 18.", new [] { "DOB" }); }
The problem with this is now the error message is showing up next to the field rather than at the top of the form (which is not good in say an accordion view since the user will be returned to the form with no visible error message). To fix this secondary problem I added this code to the Controller POST action.
ModelState.AddModelError(string.Empty, errMsgInvld);
return View(agencyVM);
}
string errMsgInvld = "There was an entry error, please review the entire form. Invalid entries will be noted in red.";
The question is still unanswered, why doesn't the model level error message show with a ViewModel (see my response to JaySilk84 for more on this)?
The issue is now that your models are nested, the error message is being placed into ModelState under Agency without the .DOB because you didn't specify it in the ValidationResult. The ValidationMessageFor() helper is looking for a key named Agency.DOB (see relevant code below from ValidationMessageFor() helper):
string fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(expression);
FormContext clientValidation = htmlHelper.ViewContext.GetFormContextForClientValidation();
if (!htmlHelper.ViewData.ModelState.ContainsKey(fullHtmlFieldName) && clientValidation == null)
return (MvcHtmlString) null;
GetFullHtmlFieldName() is returning Agency.DOB, not Agency
I think if you add the DOB to the ValidationResult it will work:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (DOB > DateTime.Now.AddYears(-18)) { yield return new ValidationResult("Must be over 18.", new List<string>() { "DOB" }); }
}
That second parameter to ValidationResult will tell it what key to use in ModelState (By default it will append the parent object which is Agency) so the ModelState will have a key named Agency.DOB which is what your ValidationMessageFor() is looking for.
Edit:
If you don't want field level validation then you don't need the Html.ValidationMessageFor(). You just need the ValidationSummary().
The view is treating AgencyVM as the model. If you want it to validate properly then put the validation at the AgencyVM level and have it validate the child objects. Alternatively you could put validation on the child objects but the parent object (AgencyVM) has to aggregate it to the view. Another thing you can do is keep it as it is and change ValidationSummary(true) to ValidationSummary(false). This will print everything in ModelState to the summary. I think removing the validation from Agency and putting it on AgencyVM might be the best approach:
public class AgencyVM : IValidatableObject
{
public Agency Agency { get; set; }
public Person Person { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Agency.DOB > DateTime.Now.AddYears(-18)) { yield return new ValidationResult("Must be over 18."); }
if (string.IsNullOrEmpty(Agency.Name)) { yield return new ValidationResult("Need a name"); }
}
}

ASP.NET MVC 3 CheckboxFor retains previous value, despite Model value

I'm attempting to add a classic Accept Terms and Conditions checkbox on the log on page of an MVC application.
If the user accepts the Terms and Conditions, but fails to log on for some other reason (bad password etc), then I want the Accept T&Cs checkbox not to be checked, so the user is forced to accept the T&Cs on every log on attempt.
The problem is that using Html.CheckboxFor(), after a postback the checkbox retains its previous value, despite the value of the bound Model property.
Here's the code, stripped down to essentials. If you run this code up, check the checkbox, and click the button, you'll be returned to the form with the checkbox still checked, even though the bound model property is false.
The Model:
namespace Namespace.Web.ViewModels.Account
{
public class LogOnInputViewModel
{
[IsTrue("You must agree to the Terms and Conditions.")]
public bool AcceptTermsAndConditions { get; set; }
}
}
The validation attribute:
public class IsTrueAttribute : ValidationAttribute
{
public IsTrueAttribute(string errorMessage) : base(errorMessage)
{
}
public override bool IsValid(object value)
{
if (value == null) return false;
if (value.GetType() != typeof(bool)) throw new InvalidOperationException("can only be used on boolean properties.");
return (bool)value;
}
}
The View:
#model Namespace.Web.ViewModels.Account.LogOnInputViewModel
#using (Html.BeginForm()) {
#Html.CheckBoxFor(x => x.AcceptTermsAndConditions)
<input type="submit" value="Log On" />
}
The Controller:
[HttpGet]
public ActionResult LogOn(string returnUrl)
{
return View(new LogOnInputViewModel { AcceptTermsAndConditions = false });
}
[HttpPost]
public ActionResult LogOn(LogOnInputViewModel input)
{
return View(new LogOnInputViewModel { AcceptTermsAndConditions = false });
}
I saw the suggestion on asp.net to add a #checked attribute to the CheckboxFor. I tried this, making the view
#model Namespace.Web.ViewModels.Account.LogOnInputViewModel
#using (Html.BeginForm()) {
#Html.CheckBoxFor(x => x.AcceptTermsAndConditions, new { #checked = Model.AcceptTermsAndConditions })
<input type="submit" value="Log On" />
}
And I saw the same behaviour.
Thanks for any help/insights!
Edit: Although I want to override the posted back value, I wish to retain the message if validation of AcceptTermsAndConditions fails (there is a validation attribute on AcceptTermsAndConditions requiring it to be true), so I can't use ModelState.Remove("AcceptTermsAndConditions") which was the otherwise sound answer #counsellorben gave me. I've edited the code above to include the validation attribute - apologies to #counsellorben for not being clearer originally.
You need to clear the ModelState for AcceptTermsAndConditions. By design, CheckBoxFor and other data-bound helpers are bound first against the ModelState, and then against the model if there is no ModelState for the element. Add the following to your POST action:
ModelState.Remove("AcceptTermsAndConditions");

ASP.NET MVC3 edit action not updating records in database

I have an edit action configured that is not updating records but not throwing any exceptions. The update appears to have worked but the changes are not reflected in the database.
I am using EF and MVC3, i have an interface that defines save customer
public interface ICustomerRepository
{
//allows a sequence of customers to be displayed
IQueryable<Customer> Customers { get; }
//saves edits to customer records
void SaveCustomer(Customer customer);
}
Then my implementation of this
public void SaveCustomer(Customer customer)
{
if (customer.CustomerId == 0)
{
context.Customers.Add(customer);
}
context.SaveChanges();
}
Then in the controller my get and post actions
public ViewResult Edit(int customerId)
{
Customer customer = repository.Customers.FirstOrDefault(c => c.CustomerId == customerId);
return View(customer);
}
[HttpPost]
public ActionResult Edit(Customer customer)
{
if (ModelState.IsValid)
{
repository.SaveCustomer(customer);
TempData["message"] = string.Format("{0} has been saved", customer.CustomerName);
return RedirectToAction("Index");
}
else
{
//there is something wrong with the data values
return View(customer);
}
}
Then in my view i have
#model CustomerOrders.Domain.Entities.Customer
#{
ViewBag.Title = "Admin: Edit" + #Model.CustomerName;
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
<h1>Edit #Model.CustomerName</h1>
using (Html.BeginForm("Edit", "Admin"))
{
<div class="left-column">
<div class="editor">#Html.EditorFor(model => model.CustomerId)</div>
<div class="label-for">#Html.LabelFor(model => model.CustomerName)</div>
<div class="editor">#Html.EditorFor(model => model.CustomerName)</div>
#Html.ValidationMessageFor(model => model.CustomerName)
</div>
<div class="middle-column">
<div class="label-for">#Html.LabelFor(model => model.PrimaryContactName)</div>
<div class="editor">#Html.EditorFor(model => model.PrimaryContactName)</div>
<div class="label-for">#Html.LabelFor(model => model.PrimaryContactNo)</div>
<div class="editor">#Html.EditorFor(model => model.PrimaryContactNo)</div>
</div>
<div class="right-column">
<input type="submit" value="Save" />
#Html.ActionLink("Cancel and return to list", "Index")
</div>
}
I also have a create method wired up to the same edit action and view which works fine. Not sure where i am going wrong, im new to MVC3 and not sure if my edit implementation is correct?
The simple answer is because your working in a stateless environment, unless your using self tracking entities, you need to Attach the object to EF's graph.
I've had problems with edit in the past though. So i ended up going to the DB to fetch the object first, then merging in the changes i need, then doing Save.
You need to seperate your Create/Edit actions out. Simply checking if the ID > 0 to deem an edit is not enough, be more explicit.
So to sum up:
Have one action method for new objects. Use context.AddObject in this scenario.
Have another action method for modifying objects. Go get the object from the repository, merge in your changes (left to right, or auto mapper, or TryUpdateModel), and do context.SaveChanges.
Overall, it's a pain. Many developers (myself included) have gone through what you have.

Why doesn't [Required] work for me? MVC3 [duplicate]

Ok I am near wits end here. I've got a simple MVC3 application with a viewmodel
ViewModel
public class TicketViewModel {
public Ticket Ticket { get; set; }
[DisplayName("Name")]
[Required(ErrorMessage = "Requestor's name is required.")]
public string Name { get; set; } }
Controller
[HttpPost]
public ActionResult Create(TicketViewModel vm)
{
if(ModelState.IsValid) {
TempData["message"] = "Your ticket has been submitted.";
TempData["message-class"] = "success";
return RedirectToAction("Index");
}
TempData["message-class"] = "error";
return View("Index", vm);
}
For some reason ModelState.IsValid is coming through as true all the time. Even when Name is left blank. It's like the model/viewmodel isn't validating at all. This works on other applications so I'm pretty sure I'm not hooking up something. I've got all the validation javascript included as well though I don't think that's the problem right now.
Update
Interestingly enough, the html tags that are being generated by #Html.TextBoxFor() are NOT including the data-val and data-val-required attributes.
View
#model MyApp.ViewModels.TicketViewModel
#{
ViewBag.Title = "Tickets";
}
<div id="main-content">
<section class="large">
<div class="section">
<div class="section-header">Submit Ticket</div>
<div class="section-content">
<div class="message"></div>
#using( Html.BeginForm("Create", "Home", FormMethod.Post) ) {
<h2>User Information</h2>
<dl>
<dt>#Html.LabelFor( m => m.Name)</dt>
<dd>
#Html.TextBoxFor( m => m.Name)
#Html.ValidationMessageFor( m => m.Name)
</dd>
<dt></dt>
<dd><button>Submit</button></dd>
</dl>
}
</div>
</div>
</section>
</div>
UPDATE II
Well now this is interesting. I created a fresh app and got things working with basic code. Then when I added DI code to the global.asax.cs validations stopped working. Specifically, when I add
public void SetupDependencyInjection() {
_kernel = new StandardKernel();
RegisterServices(_kernel);
DependencyResolver.SetResolver(new NinjectDependencyResolver(_kernel));
}
and call it from Application_Start()
protected void Application_Start()
{
SetupDependencyInjection();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
if I remove SetupDependencyInjection() validations start working. To be clear, DI works well but it seems to kill validations. This worked well prior to MVC3 Tools Update.
I was able to find a solution. Seems that when you install Ninject via nuget the configuration is a little different. It configures your application from the App_Start folder. Basically I was doubling up on my Ninject-Fu calling in from global.asax. This ended up causing the weird validation issues, though the other parts of the application were working.
Ninject - Setting up an MVC3 application
Are you perhaps using something other that the default model binder (with the DI)? I'm pretty sure that the default model binder will validate an object upon binding. If you are not using the default one, you may not experience the same behavior.
Try using
#Html.EditorFor(model => model.Name)
That should apply the data- attributes correctly
I got the same error using Ninject.Mvc together with DependencyResolver. The reason was that I created a new IKernel instance for each Bootstrapper and DependencyResolver object.
//Application_Start()
DependencyResolver.SetResolver(new NinjectDependencyResolver(NinjectBooster.CreateKernel()));
To solve the problem I've changed the code to use the same cached instance, like this:
//Application_Start()
DependencyResolver.SetResolver(new NinjectDependencyResolver(NinjectBooster.GetKernel()));
...
//NinjectMVC.cs
private static IKernel _kernel;
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
public static IKernel GetKernel()
{
if (null == _kernel)
{
_kernel = new StandardKernel();
RegisterServices(_kernel);
}
return _kernel;
}

Resources