Html.EditorForModel and Hiding element from Edit - asp.net-mvc-3

I'm using the following code to render an editor for my model using ASP.NET MVC 3, it works perfect, except for I don't want the user to see or edit the "Id" field in my object.
<% using (Html.BeginForm())
{ %>
<%: Html.ValidationSummary(true, "Your input has errors, please correct and try again") %>
<%: Html.EditorForModel(Model)%>
<input type="submit" value="Update" />
<% } %>
In my model for the ID Field I have the following
[Display(AutoGenerateField = false)]
public int Id{ get; private set; }
Which granted is what I thought would work based on the description of the "AutoGenerateField" parameter. However this isn't working. I don't want to have to build the whole editor just for this one little oddity....

Use [ScaffoldColumn(false)] to hide fields

You could use the [HiddenInput] attribute:
[HiddenInput(DisplayValue = false)]
[Display(AutoGenerateField = false)]
public int Id { get; private set; }

Related

Razor view dropdown list for a model class in MVC3

I have two model class in MVC3 one for Services which have those properties
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Image { get; set; }
public int ChildOf { get; set; }
It also have a DB table by Entityframework
Another model is Quata which have those properties
public int ID { get; set; }
public string Sender_Name { get; set; }
public string Description { get; set; }
.....
......
public Services Service_ID { get; set; }
It also have a DB table by Entityframework
I want to create a Razor(C#) view (for Quata) where user can send a quata by fill a html form but where i wanna show a dropdown list with Services ID as dropdown value and Services Name as dropdown text which is also come dynamically from the Services DB table .
My question is how i should create that dynamic dropdown list by #Html.DropDownListFor ? and send the selected data from that dropdown list to a Controller ?
Try this
Controller:
public ActionResult Create()
{
var Services = new Services();
Services.Load(); //load services..
ViewBag.ID = new SelectList(Services.ToList(), "Id", "Name");
return View();
}
[HttpPost]
public ActionResult Create(Quata Quata)
{
//save the data
}
A strong Typed View: (Using Razor)
#model Quata
#using (Html.BeginForm()) {
<fieldset>
<legend>Quata</legend>
<div>
#Html.LabelFor(model => model.Service_ID.ID, "Service")
</div>
<div>
#Html.DropDownList("ID", String.Empty)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
take a look at #Html.DropDownListFor
So say your viewmodel has a list of said Services.
Something that may work for you is the following (you may not need a for loop here, editor is supposed to eliminate that, but I had some weird binding issues).
In your top level view which points at your viewmodel (#model Quata, assuming Quata is your viewmodel) have this code :
#For i = 0 To Model.DropdownListInput.Count - 1
Dim iterator = i
#Html.EditorFor(Function(x) x.DropdownListInput(iterator), "EnumInput")
Next
In your Editor Template (create a subfolder under the view folder this dropdownlist will be in called editor templates and name the template whatever you desire, mine was EnumInput).
In your editor template, which should point at your model for Services (#model Services) have something like the following code (with substitutions for your appropriate variable names):
#<div class="editor-label">
#Html.LabelFor(Function(v) v.value, Model.DisplayName)
</div>
#<div class="editor-field">
#Html.DropDownListFor(Function(v) v.value, New SelectList(Model.ParamEnums, "ValueForScript", "EnumValue"), "--Please Select A Value--")
#Html.ValidationMessageFor(Function(v) v.value)
</div>
Replace the list with your list and the lambda values with yours (#Html.DropDownListFor(x => x.id, New SelectList(x.ServiceList, "ID", "Name"), "--Please Select A Value--") or something like that.
Note that this code is in VB, but it should provide a rough guide.

Editor Template Not working in MVC3

I am trying out the Editor Template in MVC 3
My model class is
public class BookViewModel
{
public int Id { get; set; }
public string Name { get; set; }
[DataType(DataType.Text)]
public string Author { get; set; }
}
I have create a partial view for Editor template and put that in a EditorTemplates folder with name Text.cshtml. following is the partial view
#inherits System.Web.Mvc.WebViewPage<string>
<p> Write the name of author</p> #Html.TextBox(Model)
and I used #Html.EditorFor in the view page
<p> Name : #Html.EditorFor(model => model.Name)</p>
<p> Author</p> #Html.EditorFor(model => model.Author)
But when I run the program what I see is only an empty TextBox. I should see a TextBox filled with Author Name right?
What am I missing here?
Your editor template should be:
#model String
<p> Write the name of author</p> #Html.TextBox("name of the textbox", Model)
The first parameter of the #Html.TextBox() helper can be an empty string as well, but its not recommended

ASP.NET MVC 2 - Some validation errors are not appearing

I'm testing my view/edit model's Data Annotations, and some of the errors aren't showing up. They're all property-level, but they're not showing up as either property-level or model-level. They're simply not showing up at all.
My view/edit model:
public class AdminGameEditModel
{
[Required]
public int GameID { get; set; }
[Required(ErrorMessage="A game must have a title")]
[DisplayFormat(ConvertEmptyStringToNull=false)]
public string GameTitle { get; set; }
[Required(ErrorMessage="A short URL must be supplied")]
[DisplayFormat(ConvertEmptyStringToNull=false)]
public string Slug { get; set; }
[Required(ErrorMessage="A box art image must be supplied")]
public HttpPostedFileBase BoxArt { get; set; }
[Required(ErrorMessage="A large image for the index page is required")]
public HttpPostedFileBase IndexImage { get; set; }
[Required(ErrorMessage="A game must have a review")]
[DisplayFormat(ConvertEmptyStringToNull=false)]
public string ReviewText { get; set; }
[Required(ErrorMessage="A game must have a score")]
public int ReviewScore { get; set; }
[Required(ErrorMessage="A game must have at least one Pro listed")]
[DisplayFormat(ConvertEmptyStringToNull=false)]
public string[] Pros { get; set; }
[Required(ErrorMessage="A game must have at least one Con listed")]
[DisplayFormat(ConvertEmptyStringToNull=false)]
public string[] Cons { get; set; }
[Required(ErrorMessage="A game must belong to a genre")]
public int GenreID { get; set; }
[Required(ErrorMessage="A game must be associated with at least one platform")]
public int[] PlatformIDs { get; set; }
}
The properties whose validation doesn't seem to be working properly are Pros, Cons, and GenreID. Here's how I'm trying to invoke them in my view:
<p>
<%: Html.Label("Genre") %>
<%: Html.ValidationMessageFor(model => Model.GameData.GenreID) %>
<%: Html.DropDownListFor(m => Model.GameData.GenreID, new SelectList(Model.AllGenres, "GenreID", "Name", Model.GameData.GenreID)) %>
</p>
<p>
<%: Html.LabelFor(model => Model.GameData.Pros) %><br />
<% for (var i = 0; i < 5; ++i)
{ %>
<input type="text" name="GameData.Pros" value="<%: (Model.GameData.Pros[i] != null && String.IsNullOrEmpty(Model.GameData.Pros[i])) ? "" : Model.GameData.Pros[i] %>" /><br />
<% } %>
<%: Html.ValidationMessageFor(model => Model.GameData.Pros) %>
</p>
<p>
<%: Html.LabelFor(model => Model.GameData.Cons) %><br />
<% for (var i = 0; i < 5; ++i)
{ %>
<input type="text" name="GameData.Cons" value="<%: (Model.GameData.Cons[i] != null && String.IsNullOrEmpty(Model.GameData.Cons[i])) ? "" : Model.GameData.Cons[i] %>" /><br />
<% } %>
<%: Html.ValidationMessageFor(model => Model.GameData.Cons) %>
</p>
The rest all show up fine. I'm stumped as to why those three aren't appearing. I don't see anything that jumps out to me as the cause. I'm using the default model binder and validation service.
Any ideas?
Well, for starters.. your input fields have no id's. Model validation doesn't work with names, only id's. But that's only part of the problem. The Model Binder is unlikely to be able to bind to arrays because arrays are immutable, this makes it hard to do iterative assignment to them. You're going to have to rethink this part of your application.
Second, your DropDownList has no default value. It will, in most cases just select the first item so there is no way for it to not be valid.
You may find this article interesting.

client side validation for asp.net mvc dropdown?

i just wanted to know how to enable client side validations for dropdowns in asp.net mvc 2.
The scenario would be that the dropdown will contain a "Select" item and the list of other items..,The user should select other items... the validation should fire when the user does not select the other items
public class FacilityBulletinModel
{
[DisplayName("Select a Facility")]
public List<SelectListItem> ListFacility { get; set; }
[DisplayName("Facility Bulletin")]
[Required(ErrorMessage = "Please create a Bulletin")]
public string FacilityBulletin { get; set; }
[DisplayName("Active")]
public bool Active { get; set; }
[HiddenInput(DisplayValue = false)]
public int SiteId { get;set;}
}
in my view
Select Facility <span class="err">*</span><br />
<%=Html.DropDownListFor(model => model.ListFacility, null, new {onChange="updateSiteId()" })%>
<span class="err"> <%= Html.ValidationMessageFor(model => model.ListFacility) %></span>
First, if a dropdown is required, add the [Required] attribute to your model property.
Then, enable client side validation somewhere at the top of your view:
<% Html.EnableClientValidation() %>
Then just add a validation message:
<div class="inputField">
<%= Html.LabelFor(model => model.property)%>
<%= Html.DropDownListFor(model => model.property, (SelectList)ViewData["myselelectlist"])%>
<%= Html.ValidationMessageFor(model => model.property)%>
</div>
(this requries MicrosoftMvcValidation.js to be loaded)

Wondering why DisplayName attribute is ignored in LabelFor on an overridden property

today I got confused when doing a couple of <%=Html.LabelFor(m=>m.MyProperty)%> in ASP.NET MVC 2 and using the [DisplayName("Show this instead of MyProperty")] attribute from System.ComponentModel.
As it turned out, when I put the attribute on an overridden property, LabelFor didn't seem to notice it.
However, the [Required] attribute works fine on the overridden property, and the generated errormessage actually uses the DisplayNameAttribute.
This is some trivial examplecode, the more realistic scenario is that I have a databasemodel separate from the viewmodel, but for convenience, I'd like to inherit from the databasemodel, add View-only properties and decorating the viewmodel with the attributes for the UI.
public class POCOWithoutDataAnnotations
{
public virtual string PleaseOverrideMe { get; set; }
}
public class EditModel : POCOWithoutDataAnnotations
{
[Required]
[DisplayName("This should be as label for please override me!")]
public override string PleaseOverrideMe
{
get { return base.PleaseOverrideMe; }
set { base.PleaseOverrideMe = value; }
}
[Required]
[DisplayName("This property exists only in EditModel")]
public string NonOverriddenProp { get; set; }
}
The strongly typed ViewPage<EditModel> contains:
<div class="editor-label">
<%= Html.LabelFor(model => model.PleaseOverrideMe) %>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(model => model.PleaseOverrideMe) %>
<%= Html.ValidationMessageFor(model => model.PleaseOverrideMe) %>
</div>
<div class="editor-label">
<%= Html.LabelFor(model => model.NonOverriddenProp) %>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(model => model.NonOverriddenProp) %>
<%= Html.ValidationMessageFor(model => model.NonOverriddenProp) %>
</div>
The labels are then displayed as "PleaseOverrideMe" (not using the DisplayNameAttribute) and "This property exists only in EditModel" (using the DisplayNameAttribute) when viewing the page.
If I post with empty values, triggering the validation with this ActionMethod:
[HttpPost]
public ActionResult Edit(EditModel model)
{
if (!ModelState.IsValid)
return View(model);
return View("Thanks");
}
the <%= Html.ValidationMessageFor(model => model.PleaseOverrideMe) %> actually uses [DisplayName("This should be as label for please override me!")] attribute, and produces the default errortext "The This should be as label for please override me! field is required."
Would some friendly soul shed some light on this?
Model binding and metadata using the strongly-typed helpers looks at the declared, rather than the runtime, type of the model. I consider this a bug, but apparently the MVC team disagrees with me, as my Connect issue on this was closed as "By Design."
I ran into this problem using [DisplayName("Profile Name")] and instead used [Display(Name = "Profile Name")] which fixed the problem in my case. I'm not sure if this would be useful.
The former is from System.ComponentModel whilst the latter is from System.ComponentModel.DataAnnotations.
I had the same issue when I had a partial view strongly-typed to an interface. The interface defined a DisplayName and the class that implemented the interface tried to override it. The only way I found to get it to respect the override was to type to the implementing class. I had to either change the view's model type or cast. Unfortunately, that completely negates the benefits of using the interface as the model type. I am guessing that I will end up with some level of duplicated view markup for each implementing class while not casting within the strongly-typed "helpers".
In the remote chance that this type of workaround is even remotely helpful (not getting my hopes up), here is an example. There are certainly ways of working handling into this for all possible implementing classes that try to override a name, but it is definitely more hassle than it should be.
public interface IAddressModel {
...
[DisplayName("Province")]
public string Province { get; set; }
...
}
public class UsAddressModel : IAddressModel {
...
[DisplayName("State")]
public string Province { get; set; }
...
}
<%= Html.LabelFor(m => m.State) %> <!--"Province"-->
<%= Html.LabelFor(m => (m as UsAddressModel).State) %> <!--"State"-->
Ok, I seem to have found a workaround if you don't use the Required tag with it! just use a regular expression or length attribute to determine if there is a valid entry. Hope this helps, though it's a little late.
[RegularExpression(#"^[1-9][0-9][0-9]$")] //validates that there is at least 1 in the quantity and no more than 999
[DisplayName("Quantity:")]
public string quantity { get; set; }
Still works.
In my case I was forgotten to make it a property by using getters and setters.
Instead of
public string CompanyName;
I should have used
public string CompanyName {get;set;}

Resources