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)
Related
Using an MVC5 application and I am trying to load a model within a partial view that is also within the _layout page. This doesn't seem to work as it conflicts with other models loaded up in different views.
I found an alternative with ViewBags, but it's messy and I don't think it's the best approach. Is there a way to load up a partial view within a model that's inside the _layout page so the model loaded from the partial view doesn't conflict with another model?
Updated:
What I'm trying to do is this:
In the _layout page. I'm trying to use an image carousel which is supplied by bootstrap to be interactive with the user (so the user can change the images, titles, and sub-titles).
I created a model to store the data, such as the title, etc. :
public class BannerEditor
{
public int ID { get; set; }
[Display(Name="Title")]
[StringLength(150)]
public string title { get; set; }
[Display(Name = "Sub-Title")]
[StringLength(300)]
public string subTitle { get; set; }
[Display(Name = "Image Path")]
public string imgPath { get; set; }
[Display(Name= "Starting Banner")]
public int startBanner { get; set; }
}
Then for my partial View I wrote some code and tried to load the model.:
#model IEnumerable<webby.Models.BannerEditor>
#foreach (var item in Model)
{
if (item.startBanner == 1)
{
<div class="item active">
<img src=#item.imgPath alt="...">
<div class="carousel-caption">
<h3>#item.title</h3>
<p>#item.subTitle</p>
</div>
</div>
}
else
{
<div class="item">
<img src=#item.imgPath alt="...">
<div class="carousel-caption">
<h3>#item.title</h3>
<p>#item.subTitle</p>
</div>
</div>
}
}
then in my _Layout page, I just added the Partial.
<div class="carousel-inner">
#Html.Partial("BannerLoad")
Here is the controller:
public ActionResult BannerLoad()
{
return PartialView(db.BannerEditors.ToList())
}
It gives me an error stating that it cannot load the Articles model into my partial view. The model that it needs to load is the BannerEditor. Since my _layout is loaded into every page, and the partial view is loading a model. The partial view's model conflicts with every other loaded model. The models name is "Articles".
Is there a way around this?
Use child actions for this kind of thing. They're like partial views, but they get their own context, allowing you to fetch and work with whatever model you need to without affecting the rest of the page:
Controller
[ChildActionOnly]
public ActionResult BannerLoad()
{
var banners = db.BannerEditors.ToList();
return PartialView(banners);
}
BannerLoad.cshtml
#model IEnumerable<Namespace.To.BannerEditor>
<!-- HTML to display your banners -->
_Layout.cshtml
#Html.Action("BannerLoad");
All that looks pretty similar to what you already have, but there's some key differences:
Partials don't work with actions, that's actually what makes a child action a child action and not a partial. It seems in your current code that you're expecting Html.Partial to render your BannerLoad action, but it will never do that. It will only dump the content from BannerLoad.cshtml onto the page, which because it never got fed an appropriate model, will cause an error.
Partials don't have their own context (because they don't work within a separate action), so they must receive their model from the parent view. If you don't pass a model in (which you aren't), they are automatically passed the "current" model. This will be whatever model the view the main action is using and will obviously change action to action. You cannot set a model on _Layout.cshtml, for example, and have that passed in, as that's not the origin point.
Even if you could set the model on something like _Layout.cshtml, that would only work for that one partial. If you had any other partials, you're still out of luck.
I'm working on a webapp using ASP MVC. I'm building a page to edit a user's data (model USER, view ModifyUser).
I have a model with validations in this manner:
[MetadataType(typeof(USERS_Metadata))]
public partial class USER
{
public class USERS_Metadata
{
[Required(ErrorMessage = "FALTA NOMBRE")]
[StringLength(30, ErrorMessage = "Nombre entre 3 y 30 caracteres", MinimumLength = 3)]
[RegularExpression(#"^[a-zA-Z''-'\s]{1,40}$", ErrorMessage = "Error en el formato del nombre.")]
public string NAME { get; set; }
I then use a view that automagically validates user inputs:
<div class="editor-label">
<%: Html.LabelFor(model => model.SURNAME) %>
</div>
<div class="editor-field">
<%: Html.EditorFor(model => model.SURNAME) %>
<%: Html.ValidationMessageFor(model => model.SURNAME) %>
</div>
The problem is my view is also gonna need to access some other entities with their own models, like USERCATEGORY, which makes using an strongly typed view a bit more uncomfortable.
Aditionally, and may be even more important, I don't want my view to have to deal with, and even knowing about, properties such as the user's session ID, which currently I handle like this (and i hate it):
<%: Html.HiddenFor(model => model.SESSIONID) %>
Unless I'm utterly mistaken, the most sane option is to build a custom ViewModel. I decided to build my ModifyUserViewModel to match those fields in USER I'm gonna need in my view, and add a few fields from the other models... But I have no idea of how to propagate the metadata in USER, that I use for field validation, to the new ViewModel. This metadata is automatically built from the database, and copypasting it would make me feel dead inside, even if it works.
What is the canonical, most maintenable, easiest way to validate from the View like I am currently doing, but with a ViewModel?
Try to build your view model as an aggregate of several domain models:
public class MyViewModel {
public USER User { get; set; }
public USERCATETORY Category { get; set; }
}
See a great article here.
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.
Is it possible to return a complex type from a controller to a view in asp.net mvc? All the examples I have looked at so far demonstrate passing simple intrinsic types like int, string....
You can pass any object type to the view using the ViewData Dictionary.
Just put in your controller:
ViewData["example"] = (YourObject)data;
And then in your view:
<%= ((YourObject)ViewData["example"]).YourProperty %>
And if you want to pass your object as your View model then:
return View("viewname", (YourObject)data);
And make sure your view looks like this:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<YourObject>" %>
You can create a viewmodel that's then used in the strongly typed view. You can check out this blogpost by Stephen Walther that explains it. I started out just dumping stuff in viewdata, but that gets confusing pretty quickly ;).
Use a ViewModel for your page.
you could use a view model containing both complex and simple objects, for example:
public class MyComplexViewModel
{
public Address UserAddress { get; set;}
public List<string> ValidZipCodes { get; set; }
public string Message { get; set; }
}
If your view inherits the generic ViewPage with something like this
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyComplexViewModel>" %>
you could then in the view use the view model as Model.:
<%= Html.Encode(Model.UserAddress.SomeAddressProperty) %>
<%= Html.Encode(Model.ValidZipCodes.Count) %>
<%= Html.Encode(Model.Message) %>
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.