MVC. Code first field with HiddenInput Attribute has a visible Label generated - asp.net-mvc

Using MVC5 I Have the following defined in the model
[HiddenInput(DisplayValue = false)]
public DateTime Created { get; set; }
I do not want this field to appear on any of the MVC generated views. However I am getting a label generated for this hidden field when scaffolding the views, as shown below.
What is the correct way to use this attribute so that the field and it's label are not output?

[HiddenInput(DisplayValue = false)]
public int Id { get; set; }
will be rendered as
<input id="Id" name="Id" type="hidden" />
when using Html.EditorForModel() or Html.EditorFor(m => m.Id)
Check what is render in your UI, type="hidden" or something else.

You can simply use #Html.HiddenFor inside view as shown :-
Model :-
public DateTime Created { get; set; }
View :-
#Html.HiddenFor(model=>model.Created)

I know this is an old post but I'm experiencing the same thing. My view is set up as
<div class="form-group row">
#Html.LabelFor(model => model.Summary.LeaID, htmlAttributes: new { #class = "col-form-label col-md-3" })
<div class="col-md-9">
#Html.EditorFor(model => model.Summary.LeaID, new { htmlAttributes = new { #class = "form-control"}})
#Html.ValidationMessageFor(model => model.Summary.LeaID, "", new { #class = "text-danger" })
</div>
</div>
And my Model is
[HiddenInput(DisplayValue = false)]
public string LeaID { get; set; }
When the view renders, I get the label (LabelFor) yet the EditorFor is hidden correctly.

If your only problem is that the label is showing, then annotate the model property with a Display attribute:
[HiddenInput(DisplayValue = false)]
[Display(Name ="")]
public string LeaID { get; set; }
If you do that, the label will not show but still you will have white space on the screen for where the LeaID segment was supposed to appear. Alternatively, you can manually change the view as Kartikeya Khosla has suggested.

Related

LabelFor incorrect when using AllowHtml

I'm using MVC 5.2.2.0, .net 4.5.1 and I'm seeing some odd behavior. I have a model like so:
public class Program
{
// .... Other Properties
[Display(Name = "Courses Description")]
[RichText]
[AllowHtml]
public string CoursesDescription { get; set; }
// .... Other Properties
}
RichText is a custom attribute:
[AttributeUsage(AttributeTargets.Property)]
public class RichText : Attribute
{
public RichText() { }
}
All it is used for is to tell the T4 template to add the wysi data-editor attribute to the TextAreaFor html helper.
My view has the following:
<div class="form-group">
#Html.LabelFor(model => model.CoursesDescription, htmlAttributes: new { #class = "control-label col-sm-3" })
<div class="col-sm-6">
#Html.TextAreaFor(model => model.CoursesDescription, 10, 20, new { #class = "form-control", data_editor = "wysi" })
#Html.ValidationMessageFor(model => model.CoursesDescription, "", new { #class = "text-danger" })
</div>
</div>
With the AllowHtml attribute, the View renders like this:
However, if I modify the model by removing the AllowHtml attribute, the view renders correctly.
public class Program
{
// .... Other Properties
[Display(Name = "Courses Description")]
[RichText]
public string CoursesDescription { get; set; }
// .... Other Properties
}
It is also worth pointing out that removing the RichText attribute doesn't change anything, the View still ignores the Display attribute.
Any ideas why AllowHtml is interfering with LabelFor?
Digging deeper into this, I noticed that my MVC project was using MVC 5.2.2.0, but I had inadvertently installed MVC 5.2.3.0 for my models project.
Downgrading the models project to 5.2.2.0 fixed the problem.

MVC Partial View throwing error on dropdownfor

I have a partial view I want to display as a search interface. Every time it tells me I get the error
There is no ViewData item of type IEnumerable that has the key resource_type_id.
I have tried so many things to make this work but nothing helps.
This is my view calls the partialview
#model IEnumerable<NewSAMACentral2._0.ViewModel.MemberResourcesViewModel.MemberResource>
#{
ViewBag.Title = "Add Resource To Folder";
}
<h2>Add Resource To Folder</h2>
<div>
#{Html.Partial("SearchResource", new NewSAMACentral2._0.ViewModel.MemberResourcesViewModel.ResourceSearch());}
</div>
#using (Ajax.BeginForm("InsertAttendee", "Meetings", new AjaxOptions { HttpMethod = "POST" }))
{
if (Model.Any())
{
}
}
This is my partialview
#model NewSAMACentral2._0.ViewModel.MemberResourcesViewModel.ResourceSearch
#using (Ajax.BeginForm("AddAttendee", "Meetings", new AjaxOptions { UpdateTargetId = "AddAttendee", HttpMethod = "POST" }))
{
<div class="form-group">
<label for="keyword">Keyword(s): </label>#Html.TextBox("keyword", null, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(model => Model.resource_type_id)
#Html.DropDownListFor(model => Model.resource_type_id, Model.resource_type, "-- Select --", new { #class = "form-control" })
</div>
<div class="form-group">
<label for="author">Author(s): </label>#Html.TextBox("author", null, new { #class = "form-control" })
</div>
<div class="form-group">
<input type="submit" name="submit" value="Search" />
</div>
}
This is the controller that never seems to get called...
public PartialViewResult SearchResource()
{
var results = new MemberResourcesViewModel.ResourceSearch();
results.resource_type = db.Resource_Types.Select(s => new SelectListItem
{
Text = s.name,
Value = s.id.ToString()
}).Distinct().OrderBy(x => x.Text);
return PartialView(results);
}
This is the ViewModel
namespace NewSAMACentral2._0.ViewModel
{
public class MemberResourcesViewModel
{
public IEnumerable<MemberResource> MemberResourceResult;
public MemberResource memberResource;
public class MemberResource
{
public ResourceSearch resource_search { get; set; }
[Key]
public int Id { get; set; }
[DisplayName("Resource Title")]
public string title { get; set; }
public IEnumerable<SelectListItem> resource_type { get; set; }
[DisplayName("Resource Type")]
public string resource_type_id { get; set; }
[DisplayName("Keyword")]
public string keyword { get; set; }
[DisplayName("Author")]
public string author { get; set; }
[DisplayName("Subject Type")]
public string subject_type { get; set; }
[DisplayName("Industry")]
public string industry { get; set; }
[DisplayName("Description")]
public string description { get; set; }
}
public class ResourceSearch
{
[DisplayName("Author")]
public string author { get; set; }
public IEnumerable<SelectListItem> resource_type { get; set; }
[DisplayName("Resource Type")]
public string resource_type_id { get; set; }
[DisplayName("Keyword")]
public string keyword { get; set; }
}
}
}
You have to be carefull with capital letters and put model not Model:
#Html.LabelFor(model => model.resource_type_id)
#Html.DropDownListFor(model => model.resource_type_id, model.resource_type, "-- Select --", new { #class = "form-control" })
On your main View Action (not partial view action result):
var types = db.Resource_Types.Distinct().OrderBy(x => x.Text).ToList();
SelectList typeList = new SelectList(types, "ID", "Name");
ViewBag.Types = typelist;
All that was done there was pull your objects from the DataBase. Then we turned that into a Select list with 'ID' as the value field and 'Name' as the text field. Then we put that select list in a viewbag to be used by our view.
Next In your partial view:
#Html.DropDownListFor(model => model.resource_type_id, new SelectList(ViewBag.Types, "value", "text"), "-- Select --", new { #class = "form-control" })
The only difference in this HTML is its pulling values from the select list so you never have to worry about it even hitting the partial view controller. I also changed the capital 'M' in model to a lowercase because not needed
Remember to put the code for the ViewBag in your main actionresult, not the partial view action result.
As Stephen commented below all you really need is :
#Html.DropDownListFor(model => model.resource_type_id, (SelectList)ViewBag.Types, "-Select-", ...)
Your error occurs because the value of Model.resource_type is null when used inside the DropDownListFor() method.
In your main view you use Html.Partial() to render a partial view named SearchResource.cshtml, passing it a new instance of your class ResourceSearch. But ResourceSearch does not have a default constructor which initializes the resource_type property so its null, hence the exception.
Your naming conventions and use of nested models make it difficult to understand, and you have not shown the GET method for the main view, but I suspect you are wanting to actually call the SearchResource() method on your controller which will return the partial view of the form. In which case you need to use
#{Html.RenderAction("SearchResource")}
which will call the method and return its partial. Since that method initializes a new instance of ResourceSearch and populates its resource_type property, it will no longer be null
Note you should also consider applying the [ChildActionOnly] attribute to the method so it cant be called by the user entering the url in the address bar.

Master-Detail created in one View

I have a Model with Child model.
[Table("Personnel")]
public class Personnel
{
[Key]
public int Id { get; set; }
[MaxLength(10)]
public string Code { get; set; }
[MaxLength(20)]
public string Name { get; set; }
public virtual List<PersonnelDegree> Degrees
{
get;
set;
}
}
public class PersonnelDegree
{
[Key]
public int Id { get; set; }
[ForeignKey("Personnel")]
public int PersonnelId { get; set; }
public virtual Personnel Personnel { get; set; }
[UIHint("Enum")]
public Degree Degree { get; set; }
public string Major { get; set; }
public string SubField { get; set; }
public string Location { get; set; }
}
I want to created a view for this.(Add)
I added pesonnel field to view, but how to add items for PersonnelDegree?
#using (Html.BeginForm("Add", "Personnel", FormMethod.Post, new {enctype = "multipart/form-data", #class = "form-horizontal tasi-form", id = "default"}))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, null, new {#class = "alert alert-danger "})
<div class="form-group">
#Html.LabelFor(m => m.Code, new {#class = "control-label col-lg-1"})
<div class="col-lg-3">
#Html.TextBoxFor(m => m.Code, null, new {#class = "form-control", maxlength = 10})
#Html.ValidationMessageFor(m => m.Code)
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Name, new {#class = "control-label col-lg-1"})
<div class="col-lg-3">
#Html.TextBoxFor(m => m.Name, new {#class = "form-control", maxlength = 20})
#Html.ValidationMessageFor(m => m.Name)
</div>
#Html.LabelFor(m => m.Family, new {#class = "control-label col-lg-1"})
<div class="col-lg-3">
#Html.TextBoxFor(m => m.Family, null, new {#class = "form-control", maxlength = 30})
#Html.ValidationMessageFor(m => m.Family)
</div>
</div>
Can i add multy PersonnelDegrees in this View?
Edit
I add a div in view for Degrees
<div id="Degrees">
<div id="NewDegree" style="display:none">
<div class="form-group">
<input class="form-control" id="Degrees[#].Major" name="Degrees[#].Major" value="" type="text">
// another items
</div>
</div>
</div>
and in javascript :
$(document).ready(function() {
$(function() {
$("#addItem").click(function () {
var index = $('#Degrees tbody tr').length; // assumes rows wont be deleted
var clone = $('#NewDegree').html();
// Update the index of the clone
clone.replace(/\[#\]/g, '[' + index + ']');
clone.replace(/"%"/g, '"' + index + '"');
$('#Degrees').append(clone);
});
);
});
it add a div ,But after a few seconds hide div and refresh page.
Yes, you can. There are several options how to do it:
Use Js grid-like component
Use some js grid component, i prefer jqgrid you can add data localy on your View with it and then serialize it on form POST to controller.
Advantage: You don't need to write js CRUD operations with your grid your self the only thing that you should get is how to serialize local data right way to controller.
Disadvantage: You should learn how component works and could be that some component not easy emplimentable in MVC project (I mean you could lost your model validation, data annotation etc. on client side)
Add markup with js
Write your own js to resolve this issue. Here is good basic example how to do it. The idea that you generate html with js(get js from controller) and add it to your View.
Advantage: You could do what ever you want is you know js.
Disadvantage: You lost your model validation, data annotation etc. on client side.
Use PartialView with js
Get markup from Controller with Ajax (PartialView for your PersonnelDegree) and attach it to your View with js.
Advantage: You can use all ViewModel advandages (DataAnnotations) plus you can add some tricki logic in your CRUD controller methods if you need. Also it's the most easy maintainable solution if your Project is big and have losg life cicle.
Disadvantage: You should learn how to init client side validation when markup comes from ajax call. Also usually this approach force you to write a lot of code.
I prefer last option if i have a time for this.
you can add items for PersonnelDegree using partial views.
for adding multy PersonnelDegrees in this View you need to create objects in the controller
Personnel pers = new Personnel();
PersonnelDegrees pr_obj = new PersonnelDegrees ();
ind_obj.PersonnelDegrees .Add(pr_obj );
PersonnelDegrees pr_obj1 = new PersonnelDegrees ();
ind_obj.PersonnelDegrees .Add(pr_obj1 );

ASP.NET MVC Razor - All form fields are required?

I have a form that is generated by ASP.NET.
I have some required fields, and I am using the [Required] dataAnnotation for that.
However, the elements that don't have the [Required] DataAnnotation are also required according to my webpage. These are not required at all yet I cannot submit the form if they are empty.
I used scaffolding to make the pages, jquery validator is used (by default) for the validation.
Model class (some fields have been omitted for clarity)
public class Room
{
[Key]
public int ID { get; set; }
[Required(ErrorMessage = "Please enter the minimum (default) price for this room.")]
[DataType(DataType.Currency)]
[Display(Name = "Minimum price")]
public decimal MinPrice { get; set; }
[Display(Name = "Alternative price")]
[DataType(DataType.Currency)]
public decimal AltPrice { get; set; }
}
The code that creates the form fields in de .cshtml file:
<div class="form-group">
#Html.LabelFor(model => model.MinPrice, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.MinPrice)
#Html.ValidationMessageFor(model => model.MinPrice)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.AltPrice, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.AltPrice)
#Html.ValidationMessageFor(model => model.AltPrice)
</div>
</div>
The required field correctly displays the error message as defined (thus it reads the annotations).
The non required field displays a generic error message instead ("The Alternative price field is required.").
I've searched quite a lot, but everywhere it says that if the [Required] DataAnnotation is not there, it won't be required in the form.
Make the non-required fields nullable.
I was having the same problem. I had to go into my model and put ? marks in the int fields to make them null. The fields that were set as string were fine it was just the int fields that were causing the issue.

Get DisplayAttribute of Parent Property

I have a View Model that is defined as follows:
public class VariableViewModel
{
public string TemplateName { get; set; }
public bool Enabled { get; set; }
public string Value { get; set; }
}
I am using this model in other View models:
public class CreateViewModel
{
[Display(Name="First Name")]
public VariableViewModel FirstName { get; set; }
[Display(Name="Last Name")]
public VariableViewModel LastName { get; set; }
}
I have an editor template defined for VariableViewModel:
#model VariableViewModel
#Html.HiddenFor(model => model.TemplateName)
#Html.HiddenFor(model => model.Enabled)
#Html.LabelFor(model => model.Value)
#Html.TextBoxFor(model => model.Value)
An editor template for my CreateViewModel:
#model CreateViewModel
#Html.EditorFor(model => model.FirstName)
#Html.EditorFor(model => model.LastName)
Right now my editor template is creating the label as follows:
<label for="FirstName">Value</label>
Is it possible to modify LabelFor in a way that it looks at the DisplayAttribute of the parent property to determine what it should use instead of having it be Value? I want my labels to look like:
<label for="FirstName">First Name</label>
<label for="LastName">Last Name</label>
The problem is that the Display attribute is not on the property I am creating the label for, but on the containing object. Is there a way to accomplish what I want?
In your editor template simply use the following for the label:
#Html.LabelFor(model => model.Value, ViewData.ModelMetadata.DisplayName)
We are passing the parent display name as value for the label.

Resources