MVC partial views, and complex Models - asp.net-mvc

I'm trying to populating a nested Model
The model looks something like this
public Layout {
public List<Record> Records {get;set;}
}
public Record {
public List<PlaceHolder> PlaceHolders {get;set;}
}
public PlaceHolder {
public string Label {get;set;}
}
When my form posts, using fiddler, I see that the values coming down with keys in the format
Records.Index = 0
Records.PlaceHolders.Index = 0
Records[0].PlaceHolders[0].Label = foo
Records.Index = 0
Records.PlaceHolders.Index = 1
Records[0].PlaceHolders[1].Label = bar
Records.Index = 1
Records.PlaceHolders.Index = 1
Records[1].PlaceHolders[1].Label = boo
...
A lot of these KeyNames I had to generate myself using partial views, padding a TemplateInfo with the HtmlFieldPrefix set.
When I look at my save controller, the Layout is only partially populated. It has all it's Records in the Records property. But none of the Records contain PlaceHolders.
What is wrong with my post keys?

Got it, I need these lines
Records.PlaceHolders.Index = 0
To have the Record's Index, like so
Records[1].PlaceHolders.Index = 0

Related

Database First with Multiple Tables with Foreign Keys in a Single View

I have two tables department and teacher like this:
Department table (DeptID is the primary key)
DeptID | DeptName
1 P
2 C
3 M
Teacher table (DeptID is a foreign key)
DeptID | TeacherName
1 ABC
1 PQR
2 XYZ
I have used database first approach to create a single model out of these two tables. I want to display both details in a single view like this:
TeacherName | DeptName
ABC P
PQR P
XYZ C
I tried to create controllers using scaffolding but it would provide views and CRUD operations for a single table in the model.
Is there any method using which I can map these two tables together in a single view ? or is it possible (easily achievable) when I use different models for each table in the database ?
You have to create Viewmodel.
public class DepartmentTeacher
{
public int DeptID {get;set;}
public string DeptName {get;set;}
public int TeachID {get;set;}
public string TeachName {get;set;}
}
using (var db = new SchoolContext())
{
var query = (from tc in db.Teacher
join dp in db.Department on tc.DeptID equals dp.DeptID
//where st.STUDENT_ID == Customer_Id maybe you need
select new
{
dp.DeptName,
tc.TeachName
});
foreach (var item in query)
{
DepartmentTeacher.DeptName = item.DeptName;
DepartmentTeacher.TeachName = item.TeachName;
}
}
return View(DepartmentTeacher);
You can use every process this viewmodel.However you have to description this Viewmodel on your view page.

Perform a calculation in MVC viewmodel

Trying to perform a calculation in a view model. I have two donation columns, want to add them together in the viewmodel.
This is in the ViewModel Class:
[DataType(DataType.Currency)]
public decimal ttlDonation
{
get { return Donation.GetValueOrDefault() + GuestDonation.GetValueOrDefault(); }
}
The Viewmodel builds fine, and it displays properly in the razor view using (modelItem => item.ttlDonation). Problem is when I try to SUM this expression with a LINQ query in the controller like so:
var DonateTTl = GuestViewModel.Sum(f => f.ttlDonation);
Then my code throws an error:
The specified type member 'ttlDonation' is not supported in LINQ to Entities...
I am wondering the best way to do this. I also tried this in my controller (below), where I've changed my viewmodel slightly to a basic get; set; and it still isn't working. What is the best way to do this? Should I perform the calculation on my original Model rather than my viewmodel?
var GuestViewModel = guests.Select(g => new GuestIndexViewData
{
ID = g.ID,
FRID = g.FRID,
FirstName = g.FirstName,
LastName = g.LastName,
Company = g.Company,
email = g.email,
Donation = g.Donation,
GuestFirstName = g.GuestFirstName,
GuestLastName = g.GuestLastName,
GuestCompany = g.GuestCompany,
Guestemail = g.Guestemail,
GuestDonation = g.Donation,
Attended = g.Attended,
RSVP = g.RSVP,
Guest3 = g.Guest3,
ttlDonation = (g.GuestDonation.GetValueOrDefault() + g.Donation.GetValueOrDefault())
}).OrderBy(f => f.FRID);
var DonateTTl = GuestViewModel.Sum(f => f.ttlDonation);
I know I can find a way to do this but I am looking for the best way to do this as for standards/performance.
I think picking it out will work:
var DonateTTl = GuestViewModel.Select(vm => vm.ttlDonation).Sum();

MVC Model Property by string Name

A common way to fill a table is:
#For Each item In Model
Dim currentItem = item
#<tr>
<td>currentitem.Data1</td>
<td>currentitem.Data2</td>
<td>currentitem.Data3</td>
</tr>
Next
But for some reasons (to control the order of columns), I would like to refer to the fields by their string names, something like this:
#For Each item In Model
Dim currentItem = item
#<tr>
<td>currentitem("Data1").Value</td>
<td>currentitem("Data2").Value</td>
<td>currentitem("Data3").Value</td>
</tr>
Next
Is it somehow possible?
Ok - now that we have established that you need to change the order of your view model, let's do a little bit of work to your view model to make it easier to change the order. Given that we have to change the order of how we display things, we have to have a way to track what order to display them in. To change on the fly in the view without having different views with different orders (could get messy fast) - so let's just update our model a little bit.
Let assume this is your view model
public class OriginalViewModel{
public string Data1 {get;set;}
public string Data2 {get;set;}
public string Data3 {get;set;|
}
Let's create a new class called DataProperty. This will hold the data objects as well as allow us to set a display order that we can sort on later.
public class DataProperty{
public int DisplayOrder {get;set;}
public string Data {get;set;}
}
Now, let's update your view model to be a set of these DataProperties. We are using something we can enumerate and order by the display order.
public class UpdatedViewModel{
public IEnumerable<DataProperty> DataSet {get;set;}
}
Now, you can set the display order on each one of your property elements.
var listOfItems = new List<DataProperty>();
listOfItems.Add(new DataProperty{Data = "data1", DisplayOrder = 2});
listOfItems.Add(new DataProperty{Data = "data2", DisplayOrder = 3});
listOfItems.Add(new DataProperty{Data = "data3", DisplayOrder = 1});
var model = new UpdatedViewModel();
model.Data = listOfItems;
In your view, order by the display order property. Note we can now use Linq to order our data appropriately based on the requirements for this view.
#{foreach(var item in Model.OrderBy(x=>x.Data.DisplayOrder){
<tr>
<td>#item.Data</td>
<td>#item.Data</td>
<td>#item.Data</td>
</tr>
}}
which should render in HTML
<tr>
<td>data3</td>
<td>data1</td>
<td>data2</td>
</tr>
Thank you Tommy,
I tried to solve it in simple way and did this:
For example, I have a Viewdata that contains the order of the columns:
ViewData("columnsorder")="|3|1|2|"
and then, I just loop through ViewData and set the columns.
#For Each item In Model
Dim currentItem = item
#<tr>
#For i As Integer = 1 To ViewData("columnsorder").ToString.Split("|").Count - 2
Dim ind As Integer = ViewData("columnsorder").ToString.Split("|")(i)
Select Case ind
Case 1#<td>#currentItem.Data1</td>
Case 2#<td>#currentItem.Data2</td>
Case 3#<td>#currentItem.Data3</td>
End Select
Next
</tr>
Next

Binding pivot query to view in ASP.Net MVC

I'm sticking on how to best present some data that's being dynamically generated from two different tables.
Given my query:
var assets = assetRepo.Find(x => x.LoginId == User.Identity.Name);
var accounts = repository.Find(x => x.AccStatus == "A" && x.LoginId == User.Identity.Name);
var query = from asst in assets
join acct in accounts on asst.AccountId equals acct.AccountId
select new
{
Account = acct.AccountNumber,
Status = acct.AccStatus,
Make = asst.Make,
Model = asst.Model,
Submodel = asst.SubModel,
Registration = asst.Registration,
Balance = acct.BalanceOutstanding,
NextPayment = acct.NextPayment,
Date = String.Format("{0:dd MMM yyyy}", acct.NextPaymentDate),
Due = acct.ArrearsBal
};
What would be the best (i.e. cleanest) way to bind this to the view? Would a custom class be required or is there a way to specify and iterate over a collection of anonymous types?
Creating custom class can give you additional benefits. You can use DisplayAttribute to set column headers and order. Then you can create view (or template to use with DisplayFor) that takes list of objects of any type and uses reflection to read annotations and display view nicely.
class Report {
[Display(Name="Account",Order=1)]
public string Account {get; set;}
[Display(Name="Next payment",Order=2)]
public Date NextPayment {get; set;}
}
It looks also clean. You will be able to use this annotations not only for grid, but also for excel exports or other data operations.

What is wrong with my ASP.NET MVC SelectList?

I'm trying to use a SelectList one of my views, and its just not populating correctly. It gets the proper number of entries (4), but they all read System.Web.Mvc.SelectListItem. I fired up the debugger on the code, and saw some strangeness going on. I must be doing something wrong, but I don't quite see what.
Code from the ViewModel:
public SelectList DeviceTypes {get; private set;}
....
var device_types = DataTableHelpers.DeviceTypes();
IEnumerable<SelectListItem> sl = device_types.Select(
dt => new SelectListItem { Selected = (dt.DeviceType == 1),
Text = dt.Description,
Value = dt.DeviceType.ToString() }).ToList();
DeviceTypes = new SelectList(sl);
And code from the View:
<%= Html.DropDownList("Type",Model.DeviceTypes) %>
So, when I look at this in the debugger, the sl IEnumerable is getting built correctly. I can see all 4 elements in there, with the proper Text and Value property values. Once I call the SelectList constructor however, if I expand the IEnumerable that it contains, I see that it has 4 entries, but all the data in them has been lost. The Text is set to System.Web.Mvc.SelectListItem, and the value is null.
Ive tried changing the ToList() call to a ToArray(), as well as removing it entirely. That didn't change the behaviour.
What am I doing wrong here?
EDIT: Scratch my first answer.
You should be passing the IEnumerable list if items to the View, not trying to construct a Html item in the controller.
Code for controller:
public IEnumberable<YourModel> DeviceTypes {get; internal set;}
....
DeviceTypes = DataTableHelpers.DeviceTypes();
Code for View:
<%= Html.DropDownList("Type", from dt in Model.DeviceTypes
select new SelectListItem
{
Text = dt.Description,
Value = dt.DeviceType.ToString(),
Selected = dt.DeviceType == 1
}) %>

Resources