问题
I am trying to return a list of customers to a strongly typed view using the viewbag and am having some difficulties as im new to MVC and Razor, can anyone kindly offer any advice on the following problem please?
I have the following Code in my controller,
public ViewResult Index()
{
var q = from a in db.Customers
select a;
ViewBag.customer = q;
return View(db.CustomerSites.ToList());
}
and this code in my view
@foreach (var customer in Model)
{
<tr>
<td>
@ViewBag.customer.CustomerName
<td>
<td>
@customer.UnitNo
</td>
<td>
@Truncate(customer.StreetName, 25)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id=customer.Id }) |
@Html.ActionLink("Details", "Details", new { id=customer.Id }) |
@Html.ActionLink("Delete", "Delete", new { id=customer.Id })
</td>
</tr>
}
So i am retrieving a list of customers and customer sites, the sites are typed to the view,
@model IEnumerable<trsDatabase.Models.CustomerSite>
I am trying extract CustomerName from the list of customers using
@ViewBag.customer.CustomerName
But this is generating an error saying the "Customer" type doesnt contain a defintion for customer name but it does as shown below so im not sure why the error is occuring.
namespace trsDatabase.Models
{
public class Customer
{
[ScaffoldColumn(false)]
public int Id { get; set; }
[StringLength(50), Required(ErrorMessage = "Customer name required, please enter a customer name")]
public string CustomerName { get; set; }
[DisplayName("Contact Name")]
[StringLength(50), Required(ErrorMessage = "Primary contact name required, please enter a contact name")]
public string PrimaryContactName { get; set; }
[DisplayName("Secondary Contact")]
public string SecondaryContactName { get; set; }
[DisplayName("Email")]
[StringLength(50), Required(ErrorMessage = "Primary email address is required please enter an email address")]
public string PrimaryEmailAddress { get; set; }
[DisplayName("Secondary Email")]
public string SecondaryEmailAddress { get; set; }
[ScaffoldColumn(false)]
public DateTime RegisteredDate { get; set; }
[DisplayName("Contact No")]
public string PrimaryContactNo { get; set; }
[DisplayName("Secondary Contact No")]
public string SecondaryContactNo { get; set; }
[DisplayName("Waste Carrier Ref")]
public string WasteCarrierRef { get; set; }
[DisplayName("Unit No")]
public string UnitNo { get; set; }
[DisplayName("Street Name")]
[StringLength(50), Required(ErrorMessage = "Street name required, please enter a street name ")]
public string StreetName { get; set; }
[StringLength(50), Required(ErrorMessage = "Town required, please enter a town")]
public string Town { get; set; }
[StringLength(50), Required(ErrorMessage = "County is required, please enter a county")]
public string County { get; set; }
[StringLength(10), Required(ErrorMessage = "Postcode is required, please enter a postcode")]
public string Postcode { get; set; }
public List<CustomerSite> CustomerSites { get; set; }
}
}
Update:
I still cant get this to do what I need, I have created a master view model that includes
public IEnumerable <Customer> SomeCustomer { get; set; }
public IEnumerable <CustomerSite> CustomerSites { get; set; }
Then in my view,
@model IEnumerable<trsDatabase.Models.masterViewModel>
If i try to access the model by typing using a for each
@foreach (var customer in Model)
When I type @customer. It will only let me access the two lists not the individual properties in the list.
I thought I would have been able to do this with e.g. @customer.CustomerSites.UnitNo
But the furthest I can go is @customer.CustomerSites
Do you have any ideas on what I'm doing wrong here?
回答1:
I think you can make this a bit better. First - create a new class called a ViewModel. Add this to your models folder, call it for ex. CustomerSitesViewModel.cs
In it, add a definition for
public IEnumerable Customers {get;set;} public IEnumerable CustomerSites {get;set;}
Or you can create a ViewModel CustomerSiteViewModel.cs which contains
public Customer CustomerDetails {get;set;} public CustomerSite CustomerSiteDetails {get;set;}
You could name the fields Customer and CustomerSite but I didn't do that for demo purposes so you don't get stuck in a recursive loop not realizing which one to call.
Then your view (to view one) is
@model CustomerViewViewModel
or if you need a list
@model IEnumerable
This is the preferred way as opposed to ViewBag data. It's strongly typed. easier to follow, and less error prone.
回答2:
q
is not a customer, but a sequence of customers. Therefore, when you say ViewBag.customer = q;
, the ViewBag.customer
property becomes of type IEnumerable<Customer>
, which, quite naturally, does not have a CustomerName
property.
来源:https://stackoverflow.com/questions/5910767/returning-a-list-to-strongly-typed-view-using-viewbag