Mvc2 validation summary and required metadata - asp.net-mvc

source code...
Thing is, if i specify required metadata using fluent modelmetadata provider like this=>
public class Foo
{
public string Bar { get; set; }
}
public class FooModelMetadataConfiguration : ModelMetadataConfiguration<Foo>
{
public FooModelMetadataConfiguration()
{
Configure(x => x.Bar)
.Required("lapsa") ;
}
}
And write this into my view =>
<% Html.BeginForm(); %>
<%= Html.ValidationSummary() %>
<%= Html.TextBoxFor(x=>x.Bar) %>
<% Html.EndForm(); %>
And add this to home controller =>
[HttpPost]
public ActionResult Index(Foo foo)
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View(foo);
}
It will output this html =>
<div class="validation-summary-errors">
<ul>
<li>lapsa</li>
<li>The Bar field is required.</li>
</ul>
</div>
I can't understand why 2nd error is rendered and how to omit it.
Author of System.Web.Mvc.Extensibility framework replied with =>
I think this is a known issue of asp.net mvc, i could not remember the exact location where I have read it, I suggest you post the issue in asp.net mvc issue tracker over codeplex.
But before i post anything on issue tracker - i would like to understand first what exactly is wrong.
Any help with that?

It's fixed now.

Related

Can't figure out why model is null on postback?

I'm new to ASP.NET MVC and I'm trying to create a very simple blog type site as a means of learning how everything works. But, I'm having a problem when posting from a comment form to a model which is null and I can't tell why.
On a blog post page, I have an "add comment" link which calls some JQuery to render a partial view that is strongly typed to the CommentModel. The link passes in the ID of the blog post as well and the partial is coded like:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Blog.Models.CommentModel>" %>
<% using (Html.BeginForm())
{ %>
<%: Html.HiddenFor(x => x.Post.ID) %>
<%: Html.HiddenFor(x => x.CommentID) %>
<%: Html.TextBoxFor(x => x.Name) %><br />
<%: Html.TextBoxFor(x => x.Email) %><br />
<%: Html.TextBoxFor(x => x.Website) %><br />
<%: Html.TextAreaFor(x => x.Comment) %><br />
<input type="submit" value="submit" />
<% } %>
The CommentsModel is simple and looks like this (I haven't applied any validation or anything yet):
public class CommentModel
{
public BlogPost Post { get; set; }
public int CommentID { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Website { get; set; }
public string Comment { get; set; }
}
This is then supposed to post to a simple controller action which will add the comment to the database and return the user to the page. For the sake of simplicity, I've stripped out most of the code but it looks similar to:
[HttpPost]
public ActionResult CommentForm(CommentModel model)
{
if (ModelState.IsValid)
{
}
else
{
}
}
Everything works as expected, except that when posting the comment form, the comment model is null. I can't figure out why this is null. When I view the source of the rendered partial view, I can see that the "Post.ID" is populated with the correct ID, but this is lost when the form is submitted.
Am I missing something obvious here? I've set up forms similar to this in the past and it's worked fine, I can't understand why its not now. Thanks in advance.
Later Edit:
I had typed the code incorrectly and changed the public ActionResult CommentForm(CommentModel model) from public ActionResult CommentForm(CommentModel comment) which was causing the problem.
Thanks for the help.
Similar kind of question has been answered yesterday. Check out : MVC3 - Insert using ViewModel - Object reference not set to an instance of an object
The problem I can see is , when the form is posted, the Post.ID and CommentID are passed, whereas your action is expecting a full blown object of type "CommentModel". The model binder is unable to map the post data, into the corresponding model object.
Add:
public int PostID {get; set;}
...to your model, and populate that in your controller as a hidden input. The Post object is not going to parse easily.

Client Side Validation fails when moving to viewmodel

This seems to a common question for lots of reasons that do not seem to apply to this situation. I have create page using ASP.NET MVC 2 and I was using a strongly typed view to a class generated from DataEnities framework.
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MVC_EDI.Models.wysCustomerEndPoint>"" %>
I made validation class that I bound back to the the data class.
[MetadataType(typeof(EndPointValidation))]
public partial class wysCustomerEndPoint
{
}
[Bind()]
public class EndPointValidation
{
[Required(ErrorMessage = "Please enter the end point name")]
public string CustName { get; set; }
And I was able to use client side validation on my create page. I had a requirement to add a dropdown list box on the create page, so I switched my view to use a viewmodel instead of the data class I was using.
public class CreateEditCustomerEndPointsViewModel
{
public wysCustomerEndPoint CustomerEndPoint {get; set;}
public List<SelectListItem> DefaultLocationList { get; set; }
}
and here is the view header using the new viewmodel.
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MVC_EDI.ViewModles.CreateEditCustomerEndPointsViewModel>" %>
But now when this view gets loaded I am getting an error that my formElement is null when it tries to set a value ? I error out here inteh MicrosofyMvcValidation.js file and the formElement array is null.
formElement['__MVC_FormValidation'] = this
I suspect I need to add some sort of data annotation or attribute to either my view model or something like that. But I am not sure where? And surprisingly it seems to work out just fine in FireFox 5 but bombs in IE9?
Edit: thanks for the reply. Yes I believe I am instantiating the object before adding to the ViewModel and using the Html.Helper objects? Here is the code.
wysCustomerEndPoint ep = new wysCustomerEndPoint();
ep.BuyerID = id;
var viewModel = new CreateEditCustomerEndPointsViewModel()
{
CustomerEndPoint = ep
};
return View(viewModel);
and in the view
<div class="editor-label">
<%: Html.Label("Name") %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.CustomerEndPoint.CustName) %>
<%: Html.ValidationMessageFor(model => model.CustomerEndPoint.CustName) %>
</div>
cheers
bob
You're maybe doing this, but without seeing the relevant bits of code I don't want to assume. So, make sure you are instantiating the wysCustomerEndPoint object and sending to your view from the Controller method. Also that you are using the Html Helpers for the input elements that you are validating on. Eg.
Html.TextboxFor(model => model.wysCustomerEndPoint.CustName)

Multiple partial views on one main asp.net

trying to put a strongly typed partial view on a homepage in asp.net but it wont seem to work it, here is my code
new to asp.net and partial views.
Controller :
public ActionResult VenuePartial()
{
ViewData["Message"] = _entities.VenuePartialList();
return View();
}
Repository :
public IEnumerable<Venue> VenuePartialList()
{
var list = from s in _entities.Venue
orderby s.name ascending
select s;
return list.ToList();
}
IRepository :
IEnumerable<Venue> VenuePartialList();
Index Page :
<%Html.RenderPartial("~/Views/Venue/VenuePartial.ascx");%>
Any help would be grateful asap please
regards T
Maybe you need to pass a model to this partial:
<% Html.RenderPartial("~/Views/Venue/VenuePartial.ascx", ViewData["Message"]); %>
And by the way WTF are you using ViewData["Message"] to pass a model instead of using a model and a strongly typed view:
public ActionResult VenuePartial()
{
return View(_entities.VenuePartialList());
}
and then:
<% Html.RenderPartial("~/Views/Venue/VenuePartial.ascx", Model); %>
This obviously assumes that your partial is strongly typed to IEnumerable<Venue>. If it is typed to a single Venue you might also consider using Editor/Display Templates. So in your main view:
<%= Html.DisplayForModel() %>
and in the corresponding display template (~/Views/Shared/DisplayTemplates/Venue.ascx):
<%# Control
Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<AppName.Models.Venue>" %>
<span>
<%= Html.DisplayFor(x => x.SomePropertyOfVenue) %>
</span>
and now the display template will be rendered for each item of the model collection.

Upgrade MVC1/xVal project to MVC2 and compatibilities with client side validation

I am currently looking here to migrate a project from MVC1 to MVC2. We are using xVal for client side validation.
From what I understand, I only have to remove references to xVal and replace by MVC2 EnableClientSideValidation and it should do the trick. Anything else would be required ?
Also, with xVal could not validate on client side a list of models, is it still the case with MVC2 + ClientSideValidation ? (what I mean with the "list of models" is doing validation on a List<TypeOfModel>)
Example of this is :
controller:
public ActionResult Index()
{
Models.Model1 model = new Models.Model1();
model.Usernames = new List<Models.Model2>();
model.Usernames.Add(new Models.Model2 { });
model.Usernames.Add(new Models.Model2 { });
model.Usernames.Add(new Models.Model2 { });
model.Usernames.Add(new Models.Model2 { });
return View(model);
}
Model1:
class Model1 {
public List<Model2> Usernames { get; set; }
}
Model2:
class Model2 {
[Required]
public string Username { get; set; }
}
View:
<% Html.EnableClientValidation(); %>
<% using (Html.BeginForm()) { %>
<% foreach (var username in Model.Usernames) { %>
<% Html.RenderPartial("View2", username); %>
<br /><br />
<% } %>
<input type="submit" />
<% } %>
View2:
<%= Html.EditorFor(f => f.Username) %>
<%= Html.ValidationMessageFor(a => a.Username)%>
This is a POC where MVC2 client side validation is failing since it validates by field id...
Been there, done that, got the T-Shirt. And wish I never went there -- MVC2 validation is frankly not on par with xVal once you've got xVal properly implemented. In addition, MVC3 validation is much, much better done. So, if I were jumping off xVal, I would vector towards making it work with MVC3 which is a much different beast.
Though I subscribe somewhat to what Wyatt said here especially the part about MVC3, but I have been using MVC2 client side validation and it has not been a bad experience at all.
To answer your question, you need to do the following:
1. Include MicrosoftAjax.js and MicrosoftMvcValidation.js in your view.
2. Then simply call the helper <% Html.EnableClientValidation(); %>
It should pickup your DataAnnotation model validation rules and give you client side validation without much effort.

ASP.NET MVC - MasterPageView and RenderPartials - Confusion

I'm a little confused with trying to do bring a list of Categories into a navigation bar on a MasterPageView in the latest release of the ASP.NET MVC framework.
I have 0 experience with Partials so far (this adds to the confusion).
Should I use this variant of the RenderPartial?
HtmlHelper.RenderPartial(string partialViewName, object model)
I wasn't able to find any good examples of this method. By convention there is no model associated with the MasterPageView right? So what is the proper way to push or pull data into a "partial" from the MasterPageView?
Assuming that this method is absolutely going down the wrong path:
<div id="navigation">
<%
CategoryRepository cr = new CategoryRepository();
IList<Category> lst = cr.GetCategories();
Html.RenderPartial("NavBar", lst);
%>
</div>
Do you not want your masterpage to have viewdata? You could solve it by having a base view data class that ALL your other viewdata classes inherit from...
BaseViewData.cs - this is a viewdata class that all other viewdata classes will inherit from
public class BaseViewData
{
public string Title { get; set; }
public string MetaKeywords { get; set; }
public string MetaDescription { get; set; }
IList<Category> NavCategoryList { get; set; }
}
Now in your Site.Master page simply have
<%# Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<BaseViewData>" %>
<title><%=ViewData.Model.Title %></title>
<meta name="keywords" content="<%=ViewData.Model.MetaKeywords %>" />
<meta name="description" content="<%=ViewData.Model.MetaDescription %>" />
<%= Html.RenderPartial("NavBar", ViewData.Model.NavCategoryList) %>
This could significantly impact your application architecture, but its not necessarily a bad thing.
HTHs,
Charles
public ActionResult NavBar()
{
CategoryRepository cr = new CategoryRepository();
IList<Category> lst = cr.GetCategories();
return View(lst);
}
on your partial call
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%# Import Namespace="app.Models" %>
and do all your rendering ui here
<div id="navigation">
<%
Html.RenderPartial("NavBar");
%>
</div>
you can do ActionResult calls in your controllers
I would say that since it's the Master Page you would probably have to store your data that you are passing in ViewData with a string key. If it was a regular view page it would be better to have a strongly typed page, but this is a different case. So you would probably do something this in your controller:
ViewData["MasterPageData"] = FunctionToGetData();
And then on the Master Page something like this:
<%
if (ViewData["MasterPageData"] != null)
{
Html.RenderPartial("ControlName.ascx", ViewData);
}
%>
Then in the control, process like you would on a normal view page:
<% var categories = (CastIfNeeded)ViewData["MasterPageData"]; %>
process as normal...
I haven't had to pass data to a master page yet, but that's how I would think you'd do it. More info here.
EDIT: Changed it around a little to reflect what I'm doing in my current project.
I would use Html.RenderAction() instead and return a partial view from it.

Resources