I am working on a tool so i can keep things organized in a game.
This is my class:
//The item
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Value { get; set; }
public ItemLabel Label { get; set; }
public ItemType Type { get; set; }
public ItemTradeType TradeType { get; set; }
public Trade Trade { get; set; }
}
The Label / Type / TradeType / Trade are enums.
View:
#model EveMonitorV2.Models.Item
#{
ViewBag.Title = "AddItem";
}
<h2>AddItem</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Item</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.Value)
</div>
//What should be done here?
<div class="editor-field">
#Html.EditorFor(model => model.Value)
#Html.ValidationMessageFor(model => model.Value)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Trade)
</div>
<div class="editor-field">
#Html.CheckBoxFor()
#Html.ValidationMessageFor(model => model.Trade)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
The enum has a whole list of possibilities and I want to make an Item Create view
The problem i run into:
I want to be able to select more options from the enums. (Like this)
Where the categories are my enums.
Is this possible at all in asp.net mvc 4?
(little note: I am still a student, but it isn't a school project)
Create View\Shared\EditorTemplates\Options.cshtml
#using System.ComponentModel.DataAnnotations
#using System.Reflection
#model Enum
#{
var name = ViewData.TemplateInfo.HtmlFieldPrefix;
var type = Model.GetType();
}
#foreach (Enum e in Enum.GetValues(type))
{
var display = type.GetField(e.ToString()).GetCustomAttribute<DisplayAttribute>();
if (display != null && (display.GetAutoGenerateField() ?? true))
{
<label class="checkbox" title="#display.GetDescription()">
<input type="checkbox" name="#name" value="#e.ToString()" checked="#Model.HasFlag(e)" />
#display.Name
</label>
}
}
your enum may be described as next:
[Flags]
public enum MyOptions
{
[Display(AutoGenerateField = false)]
None = 0,
[Display(Name = "Option 1 name")]
Opt1 = 1 << 1,
[Display(Name = "Option 2 name")]
Opt2 = 1 << 2,
[Display(Name = "Option 3 name")]
Opt3 = 1 << 3,
}
than, using:
<div class="editor-field">
#Html.LabelFor(m => m.Trade)
#Html.EditorFor(m => m.Trade, "Options")
</div>
Related
I have a form with several fields and am using the standard EditorFor template to edit each value. When I display in Safari and IE then the value for "Code" appears. If I show the same form in Chrome, the value for "Code" is not visible. If i do a ViewSource then I can see the correct value, just doesn't render on page. Any ideas?
public class PageViewModel
{
public int Id { get; set; }
public string Forename { get; set; }
public string Surname { get; set; }
[Display(Name = "Code")]
[RegularExpression("^[0-9]*", ErrorMessage = "Enter digits only for the code number")]
public string Code { get; set; }
}
And my Razor is:
<div class="form-group">
#Html.LabelFor(model => model.Code, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Code)
#Html.ValidationMessageFor(model => model.Code)
</div>
</div>
Update:
If I add the "Code" field in for a second time, then the second copy correctly shows the value. So confused:
<div class="form-group">
#Html.LabelFor(model => model.Code, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Code)
#Html.EditorFor(model => model.Code)
#Html.ValidationMessageFor(model => model.Code)
</div>
</div>
This is the View-Source:
<input data-val="true" data-val-regex="Enter digits only for the code number" data-val-regex-pattern="^[0-9]*" id="Code" name="Code" type="text" value="22222">
I'm working with MVC 4 EF Code First and I have an object with an Edit View and it works properly. Then I created a very similar Create View, only when I click on the submit button I don't hit any breakpoints in the Controller. How do I tell what's wrong here? Is there somewhere I can set a breakpoint in either JavaScript or code-behind?
Model
public class ThirdParty : BaseModel
{
public Int32 Id { get; set; }
[MaxLength(2)]
private String CountryCode { get; set; }
[MaxLength(6)]
private Int32 SequenceNumber { get; set; }
public String UIN
{
get
{
if (CountryCode != null && SequenceNumber > 0)
return CountryCode.ToString() + "-" + SequenceNumber.ToString();
else
return null;
}
set
{
CountryCode = value.ToString().Substring(0, 2);
SequenceNumber = Int32.Parse(value.ToString().Substring(3, value.Length-3));
}
}
[MaxLength(250)]
[Required(AllowEmptyStrings = false, ErrorMessage = "{0} is required.")]
public String Name { get; set; }
public virtual ICollection<RelationshipType> RelationshipTypes { get; set; }
// Address
public Int32 AddressId { get; set; }
[ForeignKey("AddressId")]
public virtual Address Address { get; set; }
public bool IsImported { get; set; }
public bool IsActive { get; set; }
public virtual ICollection<Attachment> Attachments { get; set; }
// constructor
public ThirdParty()
{
RelationshipTypes = new HashSet<RelationshipType>();
Attachments = new HashSet<Attachment>();
}
}
Controller Methods
public ActionResult Edit(int id)
{
ThirdPartyContext context = new ThirdPartyContext();
ThirdParty model = context.ThirdParties.Find(id);
ViewBag.Countries = context.Countries.ToList<Country>();
return View(model);
}
[HttpPost]
public ActionResult Edit(string button, ThirdParty model, int id)
{
if (button == "cancel")
return RedirectToAction("Index");
if (ModelState.IsValid)
{
ThirdPartyContext context = new ThirdPartyContext();
model.Address.Country = context.Countries.Find(model.Address.CountryId);
context.Entry(model.Address.Country).State = EntityState.Modified;
context.Entry(model.Address).State = EntityState.Modified;
context.Entry(model).State = EntityState.Modified;
context.SaveChanges();
Success("Third Party record updated!");
return RedirectToAction("Index");
}
else
{
ThirdPartyContext context = new ThirdPartyContext();
model.Address = context.Addresses.Find(model.AddressId);
return View("Edit", model);
}
}
public ActionResult Create()
{
ThirdPartyContext context = new ThirdPartyContext();
ViewBag.Countries = context.Countries.ToList<Country>();
return View();
}
[HttpPost]
public ActionResult Create(ThirdParty model)
{
if (ModelState.IsValid)
{
ThirdPartyContext context = new ThirdPartyContext();
List<ThirdParty> models = context.ThirdParties.ToList<ThirdParty>();
model.Id = models.Count() == 0 ? 1 : models.Select(x => x.Id).Max() + 1;
context.ThirdParties.Add(model);
context.SaveChanges();
Success("Your information was saved!");
return RedirectToAction("Index");
}
Error("There were some errors in your form.");
return View(model);
}
[HttpPost]
public ActionResult Create(string button, ThirdParty model)
{
if (button == "cancel")
return RedirectToAction("Index");
if (ModelState.IsValid)
{
ThirdPartyContext context = new ThirdPartyContext();
List<ThirdParty> models = context.ThirdParties.ToList<ThirdParty>();
model.Id = models.Count() == 0 ? 1 : models.Select(x => x.Id).Max() + 1;
context.ThirdParties.Add(model);
context.SaveChanges();
Success("Your information was saved!");
return RedirectToAction("Index");
}
Error("There were some errors in your form.");
return View(model);
}
Edit View
#model Models.ThirdParty
#{
ViewBag.Title = "Edit";
Layout = "~/Views/shared/ContentLayout.cshtml";
}
<div class="row">
<div class="col-lg-12">
<div class="page-header">
<h2>Third Party</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-8">
#using (Html.BeginForm("Edit", "ThirdParty", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { #class = "form-horizontal" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="form-group">
#Html.HiddenFor(model => model.Id)
<div class="clearfix visible-xs"></div>
#Html.HiddenFor(model => model.Address.Id)
</div>
<div class="form-group">
#Html.EditorFor(model => model.UIN)
<div class="clearfix visible-xs"></div>
#Html.EditorFor(model => model.Name)
</div>
#Html.HiddenFor(model => model.AddressId)
#Html.Partial("_EditAddress", Model)
#Html.HiddenFor(model => model.CreatedBy)
#Html.HiddenFor(model => model.CreatedOn)
#Html.HiddenFor(model => model.ModifiedBy)
#Html.HiddenFor(model => model.ModifiedOn)
<p>
<button name="button" type="submit" class="btn btn-default" value="cancel">Cancel</button>
<button name="button" type="submit" class="btn btn-primary" value="submit">Submit</button>
</p>
}
</div>
</div>
** Create View **
#model Models.ThirdParty
#{
ViewBag.Title = "Create";
Layout = "~/Views/shared/ContentLayout.cshtml";
}
<div class="row">
<div class="col-lg-12">
<ul class="breadcrumb" style="margin-bottom: 5px;">
<li>Third Parties</li>
<li class="active">Create New Third Party</li>
</ul>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="page-header">
<h2>Create Third Party</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-2"> </div>
<div class="col-lg-8">
#using (Html.BeginForm("Create", "ThirdParty", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { #class = "form-horizontal" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.EditorFor(model => model.UIN)
#Html.EditorFor(model => model.Name)
#Html.HiddenFor(model => model.AddressId)
#Html.Partial("_EditAddress", Model)
#Html.HiddenFor(model => model.CreatedBy)
#Html.HiddenFor(model => model.CreatedOn)
#Html.HiddenFor(model => model.ModifiedBy)
#Html.HiddenFor(model => model.ModifiedOn)
<p>
<button name="button" type="submit" class="btn btn-default" value="cancel">Cancel</button>
<input name="button" type="submit" class="btn btn-primary" value="submit" title="Submit" />
<input type="submit" value="Create" />
</p>
}
</div>
<div class="col-lg-2"> </div>
</div>
Edit:
I may have left out a critical part. I have these 4 hidden fields on the ThirdParty and Address models that I am planning to set in the controller Create method (if I can ever get in there). Here's the Model:
public class BaseModel
{
[HiddenInput(DisplayValue = false)]
public Int32 CreatedBy { get; set; }
[HiddenInput(DisplayValue = false)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime CreatedOn { get; set; }
[HiddenInput(DisplayValue = false)]
public Int32 ModifiedBy { get; set; }
[HiddenInput(DisplayValue = false)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime ModifiedOn { get; set; }
}
I was thinking that maybe my view is invalid and that's why it's not sending it to the controller. Here's how these look in the page markup:
<input data-val="true" data-val-number="The field CreatedBy must be a number." data-val-required="The CreatedBy field is required." id="Address_CreatedBy" name="Address.CreatedBy" type="hidden" value="" />
<input data-val="true" data-val-date="The field CreatedOn must be a date." data-val-required="The CreatedOn field is required." id="Address_CreatedOn" name="Address.CreatedOn" type="hidden" value="" />
<input data-val="true" data-val-number="The field ModifiedBy must be a number." data-val-required="The ModifiedBy field is required." id="Address_ModifiedBy" name="Address.ModifiedBy" type="hidden" value="" />
<input data-val="true" data-val-date="The field ModifiedOn must be a date." data-val-required="The ModifiedOn field is required." id="Address_ModifiedOn" name="Address.ModifiedOn" type="hidden" value="" />
<div class="form-group">
<input data-val="true" data-val-number="The field CreatedBy must be a number." data-val-required="The CreatedBy field is required." id="CreatedBy" name="CreatedBy" type="hidden" value="" />
<input data-val="true" data-val-date="The field CreatedOn must be a date." data-val-required="The CreatedOn field is required." id="CreatedOn" name="CreatedOn" type="hidden" value="" />
<input data-val="true" data-val-number="The field ModifiedBy must be a number." data-val-required="The ModifiedBy field is required." id="ModifiedBy" name="ModifiedBy" type="hidden" value="" />
<input data-val="true" data-val-date="The field ModifiedOn must be a date." data-val-required="The ModifiedOn field is required." id="ModifiedOn" name="ModifiedOn" type="hidden" value="" />
</div>
If your action gets called, setting a breakpoint at the beginning of your action and attaching to the process should do the trick.
Have you made sure that a POST request is sent from the browser when you click submit on your Create page ?
I haven't tried to run your code but note that you have defined two Create actions with the same name to process the POST verb.
This is likely to be ambiguous for the ASP.NET MVC as it cannot figure out what action to call.
Also, you are defining a ReturnUrl route value in the following line:
#using (Html.BeginForm("Create", "ThirdParty", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { #class = "form-horizontal" }))
This doesn't seem to be used in your action handling the POST.
Why do you have 2 submit buttons with the values "submit" and "create" ?
You can remove the Create action that takes the extra button parameter and replace the markup:
<button name="button" type="submit" class="btn btn-default" value="cancel">Cancel</button>
<input name="button" type="submit" class="btn btn-primary" value="submit" title="Submit" />
<input type="submit" value="Create" />
with something like:
<a class="btn btn-default" href="#Url.Action("Index", "ThirdParty")">Cancel</a>
<input name="button" type="submit" class="btn btn-primary" value="Create" title="Create" />
I invite you to read more documentation on how ASP.NET MVC Routing works.
I'm new to ASP.NET MVC 4 and I'm struggling with a concept that would be easy in webforms. So, if I have a Customer class, and a Customer has an Address, how can I edit both the Customer and Address on the same form in the same submit action? I would like to create an '_Edit' partial view for the Address, but I don't know how to wire the controller up if there is no submit button for the Address. I just want a single button to save all the Models in a single View.
So, I could create a new CompanyView model, view, and controller and do it that way. However, if I have many objects having Addresses it seems like a lot of work to keep creating View Models to allow you to edit both the object and the address in the same form. Is there a way to create an Address partial edit view and somehow update the Address fields in the Company Edit Controller? Or, have it somehow pass the model.Address back to the Company Edit Controller instead of null?
Edit:
Models
public class Address
{
public Int32 Id { get; set; }
[Display(Name = "Address 1")]
public String Address1 { get; set; }
[Display(Name = "Address 2")]
public String Address2 { get; set; }
[Display(Name = "City")]
public String City { get; set; }
[Display(Name = "State")]
public String State { get; set; }
[Display(Name = "Postal Code")]
public String PostalCode { get; set; }
[Display(Name = "Country")]
public String Country { get; set; }
}
public class Company
{
public Int32 Id { get; set; }
[Display(Name = "Company Name")]
public String Name { get; set; }
public Int32 AddressId { get; set; }
public virtual Address Address { get; set; }
}
Address _Edit Partial View
#model Models.Address
<div class="well">
<fieldset>
<legend>Address</legend>
#Html.EditorFor(model => model.Address1)
#Html.EditorFor(model => model.Address2)
#Html.EditorFor(model => model.City)
#Html.EditorFor(model => model.State)
#Html.EditorFor(model => model.PostalCode)
#Html.EditorFor(model => model.Country)
</fieldset>
</div>
Company Edit View
#model Models.Company
#{
ViewBag.Title = "Edit";
Layout = "~/Views/shared/ContentLayout.cshtml";
}
<div class="row">
<div class="col-lg-12">
<div class="page-header">
<h2>Edit Company</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-8">
#using (Html.BeginForm("Edit", "Company", new { #class = "bs-example form-horizontal" })) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.Id)
#Html.EditorFor(model => model.Name)
#Html.HiddenFor(model => model.AddressId)
#Html.Partial("~/Views/Address/_Edit.cshtml", Model.Address)
<p>
<button name="button" type="submit" class="btn btn-primary" value="submit">Submit</button>
</p>
}
</div>
</div>
Company Edit Controller
[HttpPost]
public ActionResult Edit(Company model, int id)
{
if (ModelState.IsValid)
{
// model.Address = NULL here!
Success("Record updated!");
return RedirectToAction("Index");
}
}
For model binding to work properly, you need to post only a Company back to your controller. Just pass your whole model onto your partial :
#model Models.Company
#{
ViewBag.Title = "Edit";
Layout = "~/Views/shared/ContentLayout.cshtml";
}
<div class="row">
<div class="col-lg-12">
<div class="page-header">
<h2>Edit Company</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-8">
#using (Html.BeginForm("Edit", "Company", new { #class = "bs-example form-horizontal" })) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.Id)
#Html.EditorFor(model => model.Name)
#Html.HiddenFor(model => model.AddressId)
#Html.Partial("~/Views/Address/_Edit.cshtml", Model)
<p>
<button name="button" type="submit" class="btn btn-primary" value="submit">Submit</button>
</p>
}
</div>
</div>
_Edit
#model Models.Company
<div class="well">
<fieldset>
<legend>Address</legend>
#Html.HiddenFor(model => model.Address.Id)
#Html.EditorFor(model => model.Address.Address1)
#Html.EditorFor(model => model.Address.Address2)
#Html.EditorFor(model => model.Address.City)
#Html.EditorFor(model => model.Address.State)
#Html.EditorFor(model => model.Address.PostalCode)
#Html.EditorFor(model => model.Address.Country)
</fieldset>
</div>
Controller
[HttpPost]
public ActionResult Edit(Company model, int id)
{
if (ModelState.IsValid)
{
// model.Address should now be available
Success("Record updated!");
return RedirectToAction("Index");
}
}
You should now see the Address navigation property of your model properly bound on post.
Edit based on question in comment
How you set up your views and partials is up to you really. The important thing to remember is that model binding works based on the names given to the form elements by the HTML helpers.
So Html.HiddenFor(m => m.Id) will result in <input name="Id"> while Html.HiddenFor(m => m.Address.Id) will result in <input name="Address.Id">. First one won't be picked up by the model binder as a navigation property of Company, second one will.
The simple route would be to just duplicate your partial view. But if it gets to the point where your partial becomes quite large and complex with a high amount of fields, you could create a partial base class that both your entities inherit of.
BaseEntityWithAddress.cs
public partial class BaseEntityWithAddress
{
public virtual Address Address { get; set; }
}
Customer.cs
public class Customer : BaseEntityWithAddress
{
// your properties, no need to redefine Address here
}
Vendor.cs
public class Vendor: BaseEntityWithAddress
{
// your properties, no need to redefine Address here
}
And then your partial view would take BaseEntityWithAddress as a model to which you would still pass the whole model.
_Edit.cshtml
#model Models.BaseEntityWithAddress
<div class="well">
<fieldset>
<legend>Address</legend>
#Html.HiddenFor(model => model.Address.Id)
#Html.EditorFor(model => model.Address.Address1)
#Html.EditorFor(model => model.Address.Address2)
#Html.EditorFor(model => model.Address.City)
#Html.EditorFor(model => model.Address.State)
#Html.EditorFor(model => model.Address.PostalCode)
#Html.EditorFor(model => model.Address.Country)
</fieldset>
</div>
And that will generate form elements with the correct names for the model binder to pick up.
So you would have 2 classes:
class Address
{
public string street {get;set;}
public string state {get;set;}
}
class Customer
{
public string name {get;set;}
public Address address {get;set;} // links to the above class.
}
your main customer view would be something like:
#model Models.Customer
#using (Html.BeginForm()
{
#Html.TextBoxFor(m => m.name)
#Html.Partial("_Edit", Model.address)
<button type="submit">Submit</button>
}
your partial:
#model Models.Address
#Html.TextBoxFor(m => m.street)
#Html.TextBoxFor(m => m.state)
then in your controller:
public ActionResult customer(Customer model)
{
// do whatever
}
I have a modal popup dialog box that loads a form to be submitted to the database. the form works fine if all the fields are filled out. If i leave blank fields and click the Create button the validation should kick in but it does not. I get the following error:
Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
Now I know what the error is. The values in the fields are null and they cannot be null to submit to the database. Also ModelState is false as well.
this is my model:
using System.ComponentModel.DataAnnotations;
using MVC_CSAlerts.Models;
namespace MVC_CSAlerts.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
public partial class csAlert
{
public int AlertID { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "Must Enter a Route")]
public string Routes { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "Must Enter an Issue")]
public string Issue { get; set; }
public string Detour { get; set; }
[DisplayName("Date")]
[DataType(DataType.DateTime)]
[Required]
public Nullable<System.DateTime> DateEntered { get; set; }
[Required]
[DisplayName("Entered By")]
public string EnteredBy { get; set; }
public Nullable<int> Count { get; set; }
[DisplayName("Send Email")]
public string SendEmail { get; set; }
[DisplayName("Is this a child alert")]
public string IsChildAlert { get; set; }
}
}
this is my view
#model MVC_CSAlerts.Models.csAlert
#{
ViewBag.Title = "Create";
}
<h2>Create New Alert</h2>
<script type="text/javascript">
$(document).ready(function () {
// We will test DataPicker
$('#DateEntered').datepicker();
// We will test tabs
$(function () {
$(document).tooltip();
});
});
</script>
#using (Ajax.BeginForm("Create","Alerts",new AjaxOptions()))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>New Alert</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Routes)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Routes)
#Html.ValidationMessageFor(model => model.Routes)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Issue)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.Issue)
#Html.ValidationMessageFor(model => model.Issue)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Detour)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.Detour)
#Html.ValidationMessageFor(model => model.Detour)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DateEntered)
#Html.ValidationMessageFor(Model => Model.DateEntered)
</div>
<div class="editor-field">
#Html.JQueryUI().DatepickerFor(model => model.DateEntered)
#Html.ValidationMessageFor(model => model.DateEntered)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Count)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Count)
#Html.ValidationMessageFor(model => model.Count)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.SendEmail)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.SendEmail, new
SelectList(new List<object>{
new{ value = "Y", text="Yes"},
new{ value = "N",text="No"}
},
"value",
"text",
"Y"))
#* #Html.EditorFor(model => model.SendEmail)*#
#Html.ValidationMessageFor(model => model.SendEmail)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.IsChildAlert)
</div> <div class="editor-field> #Html.DropDownListFor(model =>
model.IsChildAlert, new SelectList(new List<object>{
new{ value = "Y", text="Yes"},
new{ value = "N",text="No"}
},
"value",
"text",
"Y"))
#* #Html.EditorFor(model => model.IsChildAlert)*#
#Html.ValidationMessageFor(model => model.IsChildAlert)
</div>
<p>
<input type="submit" value="Create New Alert" />
</p>
</fieldset>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
How do I get the clientside validation to load? do I have to do javascript validation in the modal window?
thanks
Try moving your: #Scripts.Render("~/bundles/jqueryval") to the Parent View instead of having it in the Modal View.
My model is simple, one client can have many phone numbers :
I have represented this in Entity Framework
Generated client class is as below.
public partial class Client
{
public Client()
{
this.PhoneNumbers = new HashSet<PhoneNumber>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; }
}
And now I need to create a view page for "create client". This page should have space to enter PhoneNumbers also (ex: By default there should be two text boxes to enter phone numbers)
<fieldset>
<legend>Client</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>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
as the above "create view" we can easily give an space for "model.Name", because it is a simple property. But how can i do something similar for collection of phone numbers..??
I know that we can achieve this with ugly javascript code, but I would like to know the best easy and simple way, that we can use with ASP.NET MVC ... ?
You have to do a few things:
First create a ViewModel that has the properties you need:
public class ClientViewModel
{
public int Id {get;set;}
public string Name {get;set;}
public PhoneNumber PhoneNumber1 {get;set;}
public PhoneNumber PhoneNumber2 {get;set;}
}
Change Create to return the ClientViewModel
[HttpGet]
public ActionResult Create()
{
return View(new ClientViewModel());
}
Map the HttpPost to use the ClientViewModel and map the values to it:
[HttpPost]
public ActionResult Create(ClientViewModel clientViewModel)
{
var client = new Client();
client.Name = clientViewModel.Name;
client.PhoneNumbers.Add(clientViewModel.PhoneNumber1);
client.PhoneNumbers.Add(clientViewModel.PhoneNumber2);
db.Clients.Add(client);
db.SaveChanges();
return RedirectToAction("Index", "Client");
}
Then, finally, modify your view:
<fieldset>
<legend>Client</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.PhoneNumber1.Number)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PhoneNumber1.Number)
#Html.ValidationMessageFor(model => model.PhoneNumber1.Number)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PhoneNumber2.Number)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PhoneNumber2.Number)
#Html.ValidationMessageFor(model => model.PhoneNumber2.Number)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
For the collection you can use something like this:
#for(int i = 0; i < Model.PhoneNumbers.Count; i++)
{
<div class="editor-field">
#Html.EditorFor(model => model.PhoneNumbers[i])
#Html.ValidationMessageFor(model => model.PhoneNumbers[i])
</div>
}