Trouble posting from MVC form - asp.net-mvc

I am quite new to MVC, and am having a bit of trouble submitting a form and having the controller pick up the posted values.
What seems to be happening is that while the form does post to the correct method in the controller, the model that is passed through is full of empty values - as if it's not being populated by the form.
I've tried to create it in the same way as the default Login control, but I'm obviously missing something somewhere. Can anyone please shed any light?
My code is below:
MODEL
Public Class ContactUsDetails
Private _name As String
Private _email As String
Private _details As String
Public ReadOnly Property Name() As String
Get
Return _name
End Get
End Property
Public ReadOnly Property Email() As String
Get
Return _email
End Get
End Property
Public ReadOnly Property Details() As String
Get
Return _details
End Get
End Property
Public Sub New(ByVal name As String, ByVal email As String, ByVal details As String)
_name = name
_email = email
_details = details
End Sub
Public Sub New
End Sub
End Class
VIEW
#ModelType TestMVC.ContactUsDetails
#Code
ViewData("Title") = "ContactUs"
End Code
#Using Html.BeginForm()
#<fieldset>
<legend>Contact Us</legend>
<div class="editor-label">
#Html.LabelFor(Function(m) m.Name)
</div>
<div class="editor-field">
#Html.TextBoxFor(Function(m) m.Name)
</div>
<div class="editor-label">
#Html.LabelFor(Function(m) m.Email)
</div>
<div class="editor-field">
#Html.TextBoxFor(Function(m) m.Email)
</div>
<div class="editor-label">
#Html.LabelFor(Function(m) m.Details)
</div>
<div class="editor-field">
#Html.TextBoxFor(Function(m) m.Details)
</div>
<p>
<input type="submit" value="Submit" />
</p>
</fieldset>
End Using
CONTROLLER
Namespace TestMVC
Public Class FormsController
Inherits System.Web.Mvc.Controller
'
' GET: /Forms
Public Function ContactUs() As ActionResult
Return View()
End Function
<HttpPost()> _
Public Function ContactUs(model As ContactUsDetails) As ActionResult
If ModelState.IsValid Then
End If
Return View(model)
End Function
End Class
End Namespace

I'm not too expert with VB, but I your model should have the properties editable, looking at your code it seems that your modle is readonly. So the model binder can not fill in the values

The model binder does not populate the model by calling a constructor, but by setting property values. Hence, your model properties must not my read only.

MODEL:
public class FileSetViewModel
{
public int FileId { get; set; }
[DisplayName("From Policy")]
public string FromPolicy { get; set; }
[DisplayName("Policy location")]
public string PolicyLocation { get; set; }
[DisplayName("Policy type")]
public string PolicyType { get; set; }
[DisplayName("File name")]
public string FileName { get; set; }
[DisplayName("Device Type")]
public string DeviceType { get; set; }
}
public class FileSetListViewModel
{
public List<FileSetViewModel> FileSetList { get; set; }
}
VIEW:
#section DeviceContent {
<h2>File set</h2>
#if (Model.FileSetList.Count() > 0)
{
<table>
<caption>Files loaded on current device</caption>
<thead>
<tr>
<th scope="col">From Policy</th>
<th scope="col">Policy Location</th>
<th scope="col">Policy Type</th>
<th scope="col">File Name</th>
<th scope="col">Device Type</th>
<th scope="col">View</th>
</tr>
</thead>
<tbody>
#foreach (var fileSet in Model.FileSetList)
{
<tr>
<td>#fileSet.FromPolicy</td>
<td>#fileSet.PolicyLocation</td>
<td>#fileSet.PolicyType</td>
<td>#fileSet.FileName</td>
<td>#fileSet.DeviceType</td>
<td>View</td>
</tr>
}
</tbody>
</table>
}
}
Controller:
[HttpGet]
public ActionResult Index(int id)
{
FileSetListViewModel model = _policiesLogic.GetFilesSetForDevice(id);
return View(model);
}
[HttpPost]
public ActionResult Index(FileSetListViewModel model)
{
// preconditions
if (null == model) throw new ArgumentNullException("model");
if (ModelState.IsValid)
{
// Do stuff
}
else // Validation error, so redisplay data entry form
{
return View(model);
}
}
Even if the model is empty i always pass an instance to the view, though i could be wrong as this is my first mvc project as well...

Related

Get Null when Binding List of Object to Controller MVC Model

I am having trouble binding a model that contains list of objects for Editing method. This is the list of Factory which includes list of another object (FactoryHotline).
There is no problem when I get pass data from Controller to View. But when I try to send data from View back to Controller, some model's properties always null.
The Model is:
public class Factory
{
public Guid Id { get; set; }
public string Name { get; set; }
public List<FactoryHotline> FactoryHotlineList { get; set; }
}
public class FactoryHotline
{
public Guid Id { get; set; }
public Guid FactoryId { get; set; }
public string Caption { get; set; }
public string Hotline { get; set; }
}
This is View:
#model List<WebDataLayer.Models.Factory>
<form action="/Factories/Edit" method="POST" enctype="multipart/form-data">
#Html.AntiForgeryToken()
<div class="form-horizontal">
<table id="factoriesTable">
<thead>
<tr>
<th>Name</th>
<th class="Hotline1" >Hotline 1</th>
<th class="Hotline2" >Hotline 2</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.Count; i++)
{
#Html.HiddenFor(model => model[i].Id)
<tr>
<td>#Model[i].Name</td>
#for (int h = 0; h < Model[i].FactoryHotlineList.Count; h++)
{
<td>
<div>
<b>Caption: </b>
#Html.EditorFor(model => model[i].FactoryHotlineList[h].Caption, new { htmlAttributes = new { #class = "form-control ShortInput", id = "captionInput", maxlength = "39" } })
</div>
<div>
<b>Hotline:</b>
#Html.EditorFor(model => model[i].FactoryHotlineList[h].Hotline, new { htmlAttributes = new { #class = "form-control ShortInput", id = "hotlineInput", maxlength = "15" } })
#Html.ValidationMessageFor(model => model[i].FactoryHotlineList[h].Hotline)
</div>
</td>
}
</tr>
}
</tbody>
</table>
</form>
In my controller the method for Edit is:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit (List<Factory> factories)
{
}
Only Id has value, the other(Caption, Hotline) are always null in List<Factory> factories
This is how I am passing Data from Controller to View
// GET: Edit
public ActionResult Edit()
{
var factories = _factoryService.All().OrderBy(p => p.Name);
var list = factories.ToList();
return View("Edit", list);
}
I works fine using Entity Framework.
That is because you have used HiddenFor to keep id as hidden field. To have the value in postback, it should be a part of input element(input,select,checkbox,textarea,etc) or as hidden field.
#Html.HiddenFor(model => model[i].Name)
I would suggest using a viewmodel along with automapper in this case.

"MODEL" Does not contain a definition for “PROPERTY” and no extension method 'PROPERTY ' accepting a first argument of type 'MODEL' could be found

View:
#model IEnumerable<models.AppModel>
#using (Html.BeginForm()){
<table>
<tr>
<td>
#Html.LabelFor(model => model.Age) //error
</td>
</tr>
</table>
}
Controller:
public ActionResult Index(){
if (string.IsNullOrWhiteSpace(unitCode))
{
return View(entity.dBSet.ToList());
}
else // do something else
}
Model:
namespace models{
public class AppModel{
public short Age {get; set;}
public string Nationality {get; set;}
}
}
In the view, every property of the model class such as Model.Age, Model.Nationality has this error. How do I fix it?

modelstate error 'The Id field is required' in mvc4 application

I m using a viewmodel on my create view. Every thing works but on form post via jquery I m getting The Id field is required ModelState error. I have seen some solutions regarding adding [Bind(Exclude = "Id")] annotation in the model class but then when I call the same action method on the Update model it never binds the Id of the model and inserts a new record in db.
My viewmodel looks like
public class MemberSiteContactModel
{
public int Id { get; set; }
[Display(Name = "Name")]
[Required(ErrorMessage = "Name is required")]
public string Name { get; set; }
// More items
}
My partial view looks like
#model MemberSiteContactModel
<tr class="highlight">
<td class="col-sm-1">#Html.TextBoxFor(x => x.Name, new { #class = "name" })</td>
<td class="col-sm-2">#Html.TextBoxFor(x => x.ContactNo, new { #class = "contactNo" })</td>
<td class="col-sm-1"><input type="button" class="btn btn-xs btn-success contactSaveRow" value="Save" /></td>
<td class="col-sm-1"><input type="button" class="btn btn-xs btn-danger contactDeleteRow" value="Remove" name="btnRemoveContact" /></td>
</tr>
My controller looks like
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SaveSiteContact(MemberSiteContactModel memberSiteContactModel)
{
if (ModelState.IsValid)
{
//processing
}
}
I have also created a sample application to replicate the behavior
public class CityModel
{
public int Id { get; set; }
[Display(Name = "City")]
[Required(ErrorMessage = "City is required")]
public string City { get; set; }
}
public ActionResult Contact()
{
return View();
}
#model WebApplication3.Models.CityModel
#using (#Html.BeginForm("SaveCity", "Home", FormMethod.Post))
{
#Html.HiddenFor(x => x.Id)
#Html.TextBoxFor(x => x.City)
<input type="submit" value="Submit" />
}
[HttpPost]
public ActionResult SaveCity(CityModel cityModel)
{
if (ModelState.IsValid)
{
}
return null;
}
You're not passing the Id in, you need to add a hidden field that holds to Id otherwise how does the Id ever get passed into the posted model.
#Html.HiddenFor(x => x.Id)
I'm using MVC and have the same problem, so i check out all my create code and find that i wasn't send an empty model to the View at call time. The solution was simple; on the Create() action result, just add a line that creates a new ViewModel and set it as parameter to the View or Partial View return. Something like this:
public ActionResult Create(){
ViewModel entity = new ViewModel();
return PartialView(entity);
}
I hope that helps.

HtmlHelper.Display() & DisplayFor() not working as expected for a model

I have a view for editing a client with the line:
#Html.DisplayFor(x=>x.Orders)
in it. But it only outputs a display for the Id property, ignoring the other properties:
public class Order
{
public int Id { get; set; }
[DisplayName("Order Header")]
public string Header { get; set; }
// ... etc...
}
whereas I expect the behaviour to be:
If the object contains multiple properties, for each property the method generates a string that consists of markup for the property name and markup for the property value. MSDN
What have I missed?
the view:
#model Models.Client
#{
ViewBag.Title = "Client Details";
}
<h2>#ViewBag.Title</h2>
<fieldset>
#Html.DisplayFor(x => x.Notes, "ListOfNotes")
</fieldset>
<fieldset>
#{ Html.RenderPartial("NewNoteForm", Model); }
</fieldset>
<fieldset>
#using(#Html.BeginForm())
{
#Html.EditorForModel()
<input type="submit" value="Save"/>
}
</fieldset>
<fieldset>
#Html.DisplayFor(x => x.Orders) #* The errant bit *#
</fieldset>
<fieldset>
#{ Html.RenderPartial("NewOrderForm", Model); }
</fieldset>
The Client Model:
public class Client
{
public Client(int PId, string title, string forename, string surname)
: this()
{
PId = pId;
Title = title;
Forename = forename;
Surname = surname;
}
public Client()
{
Notes = new List<Note>();
Orders= new List<Order>();
}
public int PId { get; set; }
public string Title { get; set; }
public string Forename { get; set; }
public string Surname { get; set; }
public List<Note> Notes { get; private set; }
public List<Order> Orders { get; private set; }
}
Btw, The list of notes displays as expected.
Either Use Html.DisplayForModel(o=>o)
or call Html.DisplayFor() for each property of your current model. Something like this.
#Html.DisplayFor(model=>model.Id)
#Html.DisplayFor(model=>model.Header)
Since Orders is a list, you need a loop to display all the items in that list, like this:
<table>
<thead>
<tr>
<th>#Html.DisplayName(m => m.Title)</th>
<th>#Html.DisplayName(m => m.Orders)</th>
</tr>
</thead>
<tbody>
<tr>
<td>#Html.DisplayFor(m => m.Title)</td>
<td>
#foreach (var order in Model.Orders)
{
<div>
#Html.DisplayFor(_ => order)
</div>
}
</td>
</tr>
</tbody>
</table>
The quote:
If the object contains multiple properties...
refers to the fact the order object's properties (Id and Header) should be displayed all at once, using that single #Html.DisplayFor(_ => order) line.

Posting Ienumerable Values and Saving to M-2-M Relationship

VS'12 KendoUI InternetApplication Template C# asp.net EF Code First
My Question is how to pass both the Regular ( are passing now ) values and the Ienumerable(passing null) into my controller and saving them to the Database using EF Code First in a Many-2-Many Relationship manor.
The Following is what i have tried
Main View
#model OG.Models.UserProfiles
#using (Html.BeginForm())
{
<div class="editor-field">
<div class="Containter">
<div>
#Html.DisplayFor(model => model.UserName)
</div>
<div class="contentContainer">
#foreach (var item in Model.Prospects)
{
<table>
<tr>
<td>
#Html.Label("Current Prospects")
</td>
</tr>
<tr>
<td>
#Html.DisplayNameFor(x=>item.ProspectName)
</td>
</tr>
</table>
}
</div>
</div>
<div class="contentContainer2">
#Html.Partial("_UsersInProspectsDDL", new OG.ModelView.ViewModelUserInProspects() { Users = Model.UserName })
</div>
</div>
}
Partial View
#model OG.ModelView.ViewModelUserInProspects
<label for="prospects">Prospect:</label>
#(Html.Kendo().DropDownListFor(m=>m.Prospects)
.Name("Prospects")
.HtmlAttributes(new { style = "width:300px"}) //, id = "countys"})
.OptionLabel("Select Prospect...")
.DataTextField("ProspectName")
.DataValueField("ProspectID")
.DataSource(source => {
source.Read(read =>
{
read.Action("GetCascadeProspects", "ChangeUsersInfo")
.Data("filterProspects");
})
.ServerFiltering(true);
})
.Enable(false)
.AutoBind(false)
.CascadeFrom("Clients")
</div>
Model for PartialView
public class ViewModelUserInProspects
{
public string Clients { get; set; }
public IEnumerable<dbClient> AvailableClients { get; set; }
public string Prospects { get; set; }
public IEnumerable<dbProspect> AvailableProspects { get; set; }
public string Users { get; set; }
public IEnumerable<UserProfiles> AvailableUsers {get;set;}
}
}
Main Model
Standart SimpleMemberShipUserTable
Post Method
[HttpPost]
public ActionResult UsersInProspect(
[Bind(Include= "ProspectName, ProspectID")]
UserProfiles userprofiles, ViewModelUserInProspects values, FormCollection form)
//<- Trying different things sofar
{
if (ModelState.IsValid)
{
//string something = form["Prospects"];
int prosID = Convert.ToInt16(values.Prospects);
int UserID = userprofiles.UserID; // <- THIS VALUE is null atm.
This is where i need to save both ID's to the EF Generated / Mapped Table. Unsure how.
db.Entry(userprofiles).CurrentValues.SetValues(userprofiles);
db.Entry(userprofiles).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(userprofiles);
}
Please take a look Here
Goes over ViewModels
What EditorTemplate are and how to use them
What the GET Method would look like
What the Edit View would look like
Give you a View Example
What the Post Method would look like

Resources