I am using asp.net's modelbinder functionality to bind form values to my entity when posting from a view.
The html renders correctly in the initial view with correct option and value items.
When completing the form and posting, all values are populated correctly into the entity except the value from the dropdown list. not sure what I am doing wrong.
code attached below:
Customer Entity:
public class Customer : EntityBase
{
public virtual string Name { get; set; }
public virtual string Email { get; set; }
public virtual string Mobile { get; set; }
public virtual Store LocalStore { get; set; }
public virtual DateTime? DateOfBirth { get; set; }
public Customer(){}
public Customer(string name, string email, string mobile, Store localStore):this(name, email, mobile, localStore, null)
{
}
public Customer(string name, string email, string mobile, Store localStore, DateTime? dateOfBirth)
{
Name = name;
Email = email;
Mobile = mobile;
LocalStore = localStore;
DateOfBirth = dateOfBirth;
}
}
ViewModel:
public class CustomerViewModel {
// Properties
private IStoreRepository _StoreRepository;
public Customer Customer { get; private set; }
public SelectList Stores { get; private set; }
// Constructor
public CustomerViewModel(IStoreRepository storeRepository, Customer customer)
{
_StoreRepository = storeRepository;
Customer = customer;
Stores = new SelectList(_StoreRepository.GetAllStores(), "Id", "Name", Customer.LocalStore.Id);
}
}
Controller:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Prefix="")]Customer customer)
{
return View(new CustomerViewModel(_StoreRepository, customer));
}
View:
<%# Import Namespace="BlackDiamond.Buzz.MVCWeb.Controllers"%>
<%# Import Namespace="BlackDiamond.Buzz.Core"%>
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<CustomerViewModel>" %>
<%
Customer customer = ViewData.Model.Customer;
using (Html.BeginForm())
{
%>
<table>
<tr>
<td>Local Store:</td>
<td><%= Html.DropDownList("LocalStore", ViewData.Model.Stores)%></td>
</tr>
<tr>
<td>Name:</td><td><%= Html.TextBox("Name", customer.Name)%></td>
</tr>
<tr>
<td>Email:</td><td><%= Html.TextBox("Email", customer.Email)%></td>
</tr>
<tr>
<td>Mobile:</td><td><%= Html.TextBox("Mobile", customer.Mobile)%></td>
</tr>
</table>
<input type="submit" value="Create" />
<%}%>
Maybe because you declare LocalStore as Store type?
public virtual Store LocalStore { get; set; }
I think it should be int (if "id" property is int) or string. Not sure though.
public virtual int LocalStore { get; set; }
Had to create a custom modelbinder to retrieve the Store entity based on the guid from the dropdown list:
public class CustomerModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType == typeof(Customer))
{
// get values
string name = bindingContext.ValueProvider["Name"].AttemptedValue;
string email = bindingContext.ValueProvider["Email"].AttemptedValue;
string mobile = bindingContext.ValueProvider["Mobile"].AttemptedValue;
Guid storeId = new Guid(bindingContext.ValueProvider["LocalStore"].AttemptedValue);
Store localStore = IoC.Container.Resolve<IStoreRepository>().GetStore(storeId);
// hydrate
return new Customer(name, email, mobile, localStore);
}
else
{
return null;
}
}
}
Related
I'm building a website in ASP.Net, using MVC, and need to list a set of results
but i get error in the code
model:
public class Customers
{
public int Id { get; set; }
public string Name { get; set; }
public List<Customers> Itemlst { get; set; }
}
controller:
public ActionResult List()
{
Customers itemobj = new Customers();
return View(itemobj);
}
view:
#foreach(var item in Model.Itemlst)
{
<tr>
<td>Items ID:</td>
<td>#item.ID</td>
<td>Items Name:</td>
<td>#item.Name</td>
</tr>
}
</table>
From the NullReferenceException that you are receiving we can see that the issue is because of the Itemlst not being initialised. One of the ways to solve this is just to make sure that there is a valid list when you create the object:
public class Customers
{
public Customers()
{
Itemlst = new List<Customers>();
}
public int Id { get; set; }
public string Name { get; set; }
public List<Customers> Itemlst { get; set; }
}
So you can add values to the list in your action if need:
public ActionResult List()
{
Customers itemobj = new Customers();
var example = new Customers ();
example.Id = 1;
example.Name = "Example";
itemobj.Add();
return View(itemobj);
}
I don't know if you are just using this as an example for your question, but I can't help but notice that there is something weird. You could use something different like:
public class ViewModel // Name to what makes sense to you
{
// Some other properties...
public List<Customer> Customers { get; set; }
}
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
}
Or you could just use List<Customer> as your model in the view directly (yes, your model can be a object which is simply a list of objects).
When you pass the Customers list to the view, this list itself is the model.
Change Model.Itemlst —> Model inside the foreach loop.
This will iterate the list of customers.
i have created 2 model classes Mocmodel and mocsubmodel and set navigation property also.for each model id, there will be different submodels for a particular model id. i wanted to create am action link showing count of submodels, when i click on the count, view should display submodel details for each particular modelIDs like below
1220 FXRate count as hyperlink
public class tModel
{
public int ModelID { get; set; }
public string ModelName { get; set; }
public virtual ICollection<tSubModelcs> submodellist { get; set; }
}
public class tSubModelcs
{
public int submodelID { get; set; }
public string submodel { get; set; }
public DateTime launchdate { get; set; }
public int ModelID { get; set; }
}
in my view page i want to display the count of submodel as a link
#foreach (var m in Model)
{
<tr>
<td>#m.ModelID</td>
<td>#m.ModelName</td>
<td>
Html.ActionLink(, "findsubmodels", new { #id = m.ModelID, #class = "linkclick" })
</td>
</tr>
Nothing is clear. Which model are you sending to view ? Post your complete code with action methods. It seems like you are sending IEnumerable of tModel. If this is the case your Actionlink should be like this.
#if(m.submodellist != null)
{
#Html.ActionLink(m.submodellist.Count.ToString(), "findsubmodels",null, new { id = #m.ModelID, #class = "linkclick" })
}
Replace the null with your routevalue if any.
The model is
public class AdminTicket
{
public int Id;
public string Title;
public string Description;
public DateTime CreationDate;
}
The action is
public ViewResult EditTicket(int id)
{
return View(_ticketRepository.Tickets.FirstOrDefault(c => c.Id == id));
}
(I checked, an action give to a view the right model)
The view is
#model TicketSystemMVC5.Models.AdminTicket
#using (Html.BeginForm("EditTicket", "Admin"))
{
#Html.EditorFor(model=>model.Title)
#Html.EditorForModel()
<input type="submit" value="Save" />
#Html.ActionLink("Вернуться к списку", "Index")
}
The result is a form with Title-editor, a button and a link. Where are all the editor fields?
The EditorForModel doesn't like fields, it only renders properties - you can use the "auto-properties" quite happily:
public class AdminTicket {
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime CreationDate { get; set; }
}
Then your input fields will magically appear.
This is as documented (emphasis added):
Returns an HTML input element for each property in the model.
To test, this I created the following class:
public class AdminTicket {
public int Id { get; set; }
public string Title;
public string Description;
public DateTime CreationDate { get; set; }
}
And EditorForModel resulted in:
Hi I am developing a banking system for a school assignment. Can you pass 2 Names in a dropdownlist ex:
This is the model
public TransferModel(int bankId, int userid)
{
myAccount = new Service1Client().getAccountByID(bankId);
AccountList = new SelectList(new Service1Client().RetrieveAllAccountsByAccountId(userid), "Id", "Name");
}
I am setting Id, Name to the Select List
View:
<div class="editor-field">
Withdraw From: <%: Html.DropDownListFor(model => model.myAccount.Id, Model.AccountList)%>
</div>
the Select list will only display the name of the accounts. is their by any chance to display the name and the balance in the drop down list.
Thanks
Something like the following would be quite a tidy way of handling this:
public class AccountModel
{
public string Id { get; set; }
public string Name { get; set; }
public Decimal Balance { get; set; }
public string AccountSummary
{
get
{
return String.Format("{0} ({1:C})", Name, Balance);
}
}
}
public class TransferModel
{
public IList<AccountModel> Accounts { get; set; }
public string SelectedAccountId { get; set; }
/* Whatever other properties your view needs */
}
Type your view to TransferModel and do:
<%: Html.DropDownListFor(model => model.SelectedAccountId,
new SelectList { Model.Accounts, "Id", "AccountSummary" )%>
I can't seem to get the value of a select list to populate the value of the parent object.
I'm using a wrapper object to bind to so that I have access to the values needed for the SelectList as well as the object which needs the value.
I'm willing to bet I'm missing something basic but I can't find it.
I have these models:
public class Status
{
public virtual int Id { get; protected set; }
public virtual string Name { get; set; }
public virtual bool IsClosed { get; set; }
public override string ToString()
{
return Name;
}
}
public class Issue
{
public virtual int Id { get; protected set; }
public virtual string Title { get; set; }
public virtual string Description { get; set; }
public virtual Status Status { get; set; }
public virtual DateTime CreatedOn { get; set; }
public virtual DateTime UpdatedOn { get; set; }
}
And a FormViewModel (from NerdDinner examples) to contain the list of Statuses
public class IssueFormViewModel
{
public Issue Issue { get; set; }
public SelectList Statuses { get; set; }
public IssueFormViewModel(Issue issue, IList<Status> statuses)
{
Issue = issue;
Statuses = new SelectList(statuses, "Id", "Name", statuses[1].Id );
}
public IssueFormViewModel() { }
}
My Create Actions on the Controller look like...
public ActionResult Create()
{
IList<Status> statuses;
Issue issue = new Issue();
// NHibernate stuff getting a List<Status>
return View(new IssueFormViewModel(issue,statuses));
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(IssueFormViewModel issueFormView)
{ // At this point issueFormView.Issue.Status == null
// ...
}
My Issue object is bound partially except the status using these names in the View:
<p>
<label for="Issue.Title">Title:</label>
<%= Html.TextBox("Issue.Title", Model.Issue.Title)%>
<%= Html.ValidationMessage("Title", "*") %>
</p>
<p>
<label for="Statuses">Status:</label>
<!-- also tried "Issue.Status" -->
<%= Html.DropDownList("Statuses", Model.Statuses)%>
<%= Html.ValidationMessage("Status", "*")%>
</p>
I tried the dropdown list on my computer and it works, you should make sure NHibernate is bringing back more than 1 item as your code is trying to set the selected item to be the second item.
Statuses = new SelectList(statuses, "Id", "Name", statuses[1].Id);
Remember that Lists a re zero based indexed.
As expected - it WAS something simple.
I changed the view to look like:
<label for="Status.Id">Status:</label>
<%= Html.DropDownList("Status.Id", Model.Statuses)%>
<%= Html.ValidationMessage("Status.Id", "*")%>
and the controller signature to take an "issue" (can't bind to a selectlist!)
[AcceptVerbs(HttpVerbs.Post)]
//public ActionResult Create(IssueFormViewModel issueFormView)
public ActionResult Create(Issue issueToAdd)
{
And in my Post-Create action I have an Issue with a Status. Albeit the status is invalid (it only contains the Id). So before commiting the Issue to the db, I set the issueToAdd like this:
issueToAdd.Status = (from p in GetAllStatuses()
where p.Id == issueToAdd.Status.Id
select p).First();
Edit: And it turns out I didn't even need to fetch a "proper" Status object. It's bound to Id and that's good enough.