I have the classes:
public class PersonDetailsModel
{
public string FistName
{
get;
set;
}
public string LastName
{
get;
set;
}
public string Email
{
get;
set;
}
}
public class RegisterCoupleModel
{
public PersonDetailsModel Groom
{
get;
set;
}
public PersonDetailsModel Bride
{
get;
set;
}
public string UrlKeyword
{
get;
set;
}
public string ReCaptcha
{
get;
set;
}
}
folder Shared > EditorTemplates
PersonDetailsModel.cshtml
#model BindSolution.AndMarried.ViewModel.PersonDetailsModel
<div class="editor-label">
#Html.LabelFor(m => m.FistName)
</div>
<div class="editor-field">
#Html.EditorFor(m => m.FistName)
#Html.ValidationMessageFor(m => m.FistName)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.LastName)
</div>
<div class="editor-field">
#Html.EditorFor(m => m.LastName)
#Html.ValidationMessageFor(m => m.LastName)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.Email)
</div>
<div class="editor-field">
#Html.EditorFor(m => m.Email)
#Html.ValidationMessageFor(m => m.Email)
</div>
In my View:
#Html.EditorForModel()
Only the UrlKeyword and ReCapcha fields are displayed!
Why Asp.net MVC not use templantes in shared folder to display my nested type PersonDetailsModel ?
You know, you could have just edited your other question. :)
Anyway, i don't think that will work. You either need to control the entire template yourself, or let MVC do it all itself. (i could be wrong)
Create an editor template for RegisterCoupleModel:
#model BindSolution.AndMarried.ViewModel.RegisterCoupleModel
#Html.EditorFor(model => model.Groom)
#Html.EditorFor(model => model.Bride)
#Html.EditorFor(model => model.UrlKeyword)
#Html.EditorFor(model => model.ReCapcha)
Or you could use a [UIHint("PersonDetailsModel"] attribute on your Groom and Bride properties in your ViewModel.
Read up on the remarks section in EditorForModel for how this all works.
Related
I try to validate the user message by using helperclass but its does not hit the httpPost method ,
In controller i have written below codings
[HttpPost]
public ActionResult Create(ItineraryItem data)
{
return View();
}
In model, i have defined the class ItineraryItem
public class ItineraryItem
{
public DateTime? When { get; set; }
public string Description { get; set; }
public int? Duration { get; set; }
}
In view page
<div class="editor" >
#using (Html.BeginForm())
{
<p>
#Html.LabelFor(m => m.Description)
#Html.TextBoxFor(m => m.Description)
#Html.ValidationMessageFor(m => m.Description)
</p>
<p>
#Html.LabelFor(m => m.When)
#Html.TextBoxFor(m => m.When)
#Html.ValidationMessageFor(m => m.When)
</p>
<p>
#Html.LabelFor(m => m.Duration)
#Html.TextBoxFor(m => m.Duration)
#Html.ValidationMessageFor(m => m.Duration)
</p>
<p>
<input type="submit" value="Save" />
</p>
}
I'm sure there have been tons of people asking this type of question but I can't quite figure out how to word it.
I will try to explain. I am working to model an ethernet network where devices have ip addresses. I've setup my entity framework models so that the ip and subnet are stored in a separate table to ensure uniqueness across the system.
I'd like the user to be able to create a device and its associated IP at the same time if the IP they want is not already in a dropdown list.
I setip a partial of the IP Address page RenderPartial on the device page and I get this error:
Here is the question, How do I fix this error:
The model item passed into the dictionary is of type PcnWeb.Models.Device, but this dictionary requires a model item of type PcnWeb.Models.IPAddress.
Here are my models:
IP Address Model:
namespace PcnWeb.Models
{
public class IPAddress
{
public virtual ICollection<Device> Devices { get; set; }
[Key]
public int ipAddressRecId { get; set; }
public Nullable<int> ipOctet1 { get; set; }
public Nullable<int> ipOctet2 { get; set; }
public Nullable<int> ipOctet3 { get; set; }
public Nullable<int> ipOctet4 { get; set; }
public Nullable<int> smOctet1 { get; set; }
public Nullable<int> smOctet2 { get; set; }
public Nullable<int> smOctet3 { get; set; }
public Nullable<int> smOctet4 { get; set; }
}
}
And the Device Model:
namespace PcnWeb.Models
{
public class Device
{
[Key]
public int deviceRecId { get; set; }
public int ipAddressRecId { get; set; }
[Required, StringLength(64)]
[Unique]
public string Name { get; set; }
[StringLength(256)]
public string Comment { get; set; }
public virtual IPAddress IPAddress { get; set; }
}
}
I would have thought that it would be pretty easy to have the associated device creation page with an inline ipaddress creation page.
Here's the Device page:
#model PcnWeb.Models.Device
#{
ViewBag.Title = "Create a Device";
}
<h2>Create</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Device</legend>
<div class="editor-label">
#Html.LabelFor(model => model.ipAddressRecId, "IPAddress")
</div>
<div class="editor-field">
#Html.DropDownList("ipAddressRecId", String.Empty)
#Html.ValidationMessageFor(model => model.ipAddressRecId)
</div>
#{
Html.RenderPartial("~/Views/IP_Address/_Create.cshtml");
}
<div class="editor-label">
#Html.LabelFor(model => model.Name, "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.Comment, "Comment")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Comment)
#Html.ValidationMessageFor(model => model.Comment)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Here is the IP Address Partial:
EDIT: Sorry I forgot to include this
#model PcnWeb.Models.IPAddress
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>IPAddress</legend>
<div class="editor-label">
#Html.LabelFor(model => model.ipOctet1, "ipOctet1")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ipOctet1)
#Html.ValidationMessageFor(model => model.ipOctet1)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ipOctet2, "ipOctet2")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ipOctet2)
#Html.ValidationMessageFor(model => model.ipOctet2)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ipOctet3, "ipOctet3")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ipOctet3)
#Html.ValidationMessageFor(model => model.ipOctet3)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ipOctet4, "ipOctet4")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ipOctet4)
#Html.ValidationMessageFor(model => model.ipOctet4)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.smOctet1, "smOctet1")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.smOctet1)
#Html.ValidationMessageFor(model => model.smOctet1)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.smOctet2, "smOctet2")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.smOctet2)
#Html.ValidationMessageFor(model => model.smOctet2)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.smOctet3, "smOctet3")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.smOctet3)
#Html.ValidationMessageFor(model => model.smOctet3)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.smOctet4, "smOctet4")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.smOctet4)
#Html.ValidationMessageFor(model => model.smOctet4)
</div>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
So from all this, it looks great to me, the validation works client side. I'll have to write some javascript to hide the IP address partial unless they select new from the dropdown list.
Here is the question again, How do I fix this error:
The model item passed into the dictionary is of type PcnWeb.Models.Device, but this dictionary requires a model item of type PcnWeb.Models.IPAddress.
This errors means that there is mismatch between model type in your partial view and type of model passed to this view. But as i can see you trying to render the partial view without model passing.
Your code example worked for me.
So, to solve this problem you can do the next steps.
Ensure that the view path is right;).
Try so 'send' model to your partial view explicity like
main view
#model PcnWeb.Models.Device
//some code here
#Html.Partial("path_to_view", Model)
partial view.
#model PcnWeb.Models.Device
#Html.DropdownListFor(x=>x.ipAddressRecId, YourDlistSource) //or anything you need
this works for me.
Alternatively if you need edit submodel in partial view you can do this
#model PcnWeb.Models.Device
//some code here
#Html.Partial("path_to_view", Model.IPAddress)//pass the submodel to partial view
then your partial view must be with another type.
#model PcnWeb.Models.IPAddress
//some code here
Answer on comment. To resolve object reference exception try initialize your submodel in constructor.
public class Device
{
///properties
public Device()
{
IPAddress = new IPAddress();
}
}
I am developing a simple blog application to teach myself C# and asp .net mvc3.
I am stuck at a stage where I need to update comments to a post.
Comment class in my code is as follows:
public class Comment
{
public int CommentID { get; set; }
public string Name { get; set; }
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[DataType(DataType.MultilineText)]
public string CommentBody { get; set; }
public int BlogID { get; set; }
public virtual Blog Blog { get; set; }
}
I have a comment form on the blog details page which takes the name, email and comment. The code is as follow:
<div class="editor-label">
#Html.LabelFor(model => model.Comment.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Comment.Name)
#Html.ValidationMessageFor(model => model.Comment.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Comment.Email)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Comment.Email)
#Html.ValidationMessageFor(model => model.Comment.Email)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Comment.CommentBody)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Comment.CommentBody)
#Html.ValidationMessageFor(model => model.Comment.CommentBody)
</div>
<p>
<input type="submit" value="Add Comment" />
</p>
I am not sure how to pass the blogid with this so that the comment gets updated with the correct blogid.
thanks.
You could use a hidden field inside the form:
#Html.HiddenFor(x => x.Comment.BlogID)
#Html.HiddenFor(model => model.Comment.BlogID)
I have a simple ViewModel
public class ProductViewModel
{
[Required(ErrorMessage = "This title field is required")]
public string Title { get; set; }
public double Price { get; set; }
}
here's my form based on this View Model.
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>ProductViewModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Price)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Price)
#Html.ValidationMessageFor(model => model.Price)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
I dont want to validate the price field. but it got automatically validated, if nothing entered, will show this field is required. I notice I use double for price. If I changed it to "string". validation is removed. why type "double" cause automatic validation?
I dont want to validate the price field. but it got automatically validated, if nothing entered, will show this field is required
Because a double is a value type, which cannot be null. If you want the value to allow not having a value, use a nullable double: double? on your model:
public class ProductViewModel
{
[Required(ErrorMessage = "This title field is required")]
public string Title { get; set; }
public double? Price { get; set; }
}
Because double is a value type, and cannot be null. You could have made it double? or Nullable<double> and it would be fine.
Here's what I have so far Model and View:
public class RegisterModel
{
[Required]
[Display(Name = "Usuario")]
public string UserName { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Correo")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Contraseña")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirme Su Contraseña")]
[Compare("Password", ErrorMessage = "Sus contraseñas no son las mismas.")]
public string ConfirmPassword { get; set; }
[Required]
[Display(Name = "Direccion")]
public string Address { get; set; }
[Required]
[Display(Name = "Telefono Fijo")]
public string Telephone { get; set; }
[Required]
[Display(Name = "Celular")]
public string MobilePhone { get; set; }
[Required]
[Display(Name = "Fecha de Nacimiento")]
public DateTime DateOfBirth { get; set; }
[Required]
[Display(Name = "Sexo")]
public bool Sex { get; set; }
[Required]
[Display(Name = "Pais")]
public int Country { get; set; }
}
#model Foo.WebUI.Models.RegisterModel
#{
ViewBag.Title = "Register";
}
<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>
<div id="registerform">
<h2>Cree Su Cuenta</h2>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<h3>Informacion de Usuario</h3>
<div class="editor-field">
#Html.LabelFor(model => model.UserName)
#Html.EditorFor(model => model.UserName)
#Html.ValidationMessageFor(model => model.UserName)
</div>
<div class="editor-field">
#Html.LabelFor(model => model.Email)
#Html.EditorFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
</div>
<div class="editor-field">
#Html.LabelFor(model => model.Password)
#Html.EditorFor(model => model.Password)
#Html.ValidationMessageFor(model => model.Password)
</div>
<div class="editor-field">
#Html.LabelFor(model => model.ConfirmPassword)
#Html.EditorFor(model => model.ConfirmPassword)
#Html.ValidationMessageFor(model => model.ConfirmPassword)
</div>
<h3>Informacion Personal</h3>
<div class="editor-field">
#Html.LabelFor(model => model.Address)
#Html.EditorFor(model => model.Address)
#Html.ValidationMessageFor(model => model.Address)
</div>
<div class="editor-field">
#Html.LabelFor(model => model.Telephone)
#Html.EditorFor(model => model.Telephone)
#Html.ValidationMessageFor(model => model.Telephone)
</div>
<div class="editor-field">
#Html.LabelFor(model => model.MobilePhone)
#Html.EditorFor(model => model.MobilePhone)
#Html.ValidationMessageFor(model => model.MobilePhone)
</div>
<div class="editor-field">
#Html.LabelFor(model => model.DateOfBirth)
#Html.EditorFor(model => model.DateOfBirth)
#Html.ValidationMessageFor(model => model.DateOfBirth)
</div>
<div class="editor-field">
#Html.LabelFor(model => model.Sex)
#Html.EditorFor(model => model.Sex)
#Html.ValidationMessageFor(model => model.Sex)
</div>
<div class="editor-field">
#Html.LabelFor(model => model.Country)
#Html.EditorFor(model => model.Country)
#Html.ValidationMessageFor(model => model.Country)
</div>
<p>
<input type="submit" value="Create" />
</p>
}
</div>
Now, since my User will belong to a single country, in the database it has a foreign key reference to the Country table. In my model, I set the Country property to be of type int. Is this correct?
How would I correctly set this up so a dropdownlist is shown for choosing a country in the View but a numerical value is saved for persistance to the database?
Your CountryId can remain an int (or any type you use for your ids). The Select List can be initialized with the appropriate value field for the selection, and the type will match without the need for conversion.
Your model will have to be part of a viewmodel that provides to the view what is needed to make the drop down list working (mostly a SelectList ).
public class RegisterViewModel
{
public RegisterModel register { get; set; }
public SelectList SelectCountriesList { get; set; }
}
The initilisation of this ViewModel will depend on how you work in your controller.