My ViewModel looks that:
public class WerehouseViewModel
{
public Werehouse Werehouse { get; set; }
public WerehouseKey WerehouseKey { get; set; }
}
That's how I get data from database
var viewModel =
from Wh in db.Werehouses
join WhK in db.WerehouseKeys on Wh.WhID equals WhK.WhID
where Wh.WhID == id
select new WerehouseViewModel { Werehouse = Wh, WerehouseKey = WhK };
return View(viewModel);
I know I have to use IEnumerable type to show in my View, but I would like to show only one Werehouse (and only one is in view model) and Keys (let's say that there are three keys for one werehouse). How can I show one Werehouse in list and below all keys in table? Because when I use
#foreach (var x in Model)
{
<div>#x.Werehouse.Kod_magazynu</div>
<div>#x.Werehouse.Ulica</div>
<div>#x.Werehouse.Numer_magazynu</div>
<div>#x.Werehouse.Miasto</div>
}
It shows 3 times same data.
You can get the first warehouse only from your model:
#{
var warehouse = Model.Select(x=> x.Werehouse).FirstOrDefault();
<div>#warehouse.Kod_magazynu</div>
<div>#warehouse.Ulica</div>
<div>#warehouse.Numer_magazynu</div>
<div>#warehouse.Miasto</div>
}
Then you can loop to show the keys:
#foreach (var x in Model)
{
<div>#x.WerehouseKey.SomeProperty</div>
}
Related
I have a simple problem. In my controller I take join of two tables and return like this:
data = ...
select new { Contacts = item, Applications = items, Answers = j }
This is working fine. I am getting what I want: e.g. 62 data objects with the attribues I want.
But in the view how do I access these set of data points?
simple #model dynamic is not working? There must be some way to do this.
The best way to do that is by creating a ViewModel which will contain all the attributes that you need to display in your view.
public class DataViewModel {
public Contacts {get;set}
public Application {get;set;}
public Answers {get;set;}
}
Create a list of your "DataViewModel"
List<DataViewModel> Datas = new List<DataViewModel>();
After doing that, you will have to assign the values of each element in your controller after getting them from your "data" variable that you created by simply using a foreach loop.
foreach (var instance of data) {
// Assign those values here
}
You'll have to pass the list of your data (ViewModel) to your view from your controller like this :
return View(Datas);
and to call the list of your ViewModel in your view like this :
#model IEnumerable<models.DataViewModel>
Create an 'umbrella' model like:
public DataModel
{
public Contacts contacts {get;set}
public Application applications {get;set;}
public Answers answers {get;set;}
}
On controller:
select new DataModel(){ Contacts = item, Applications = items, Answers = j }
And have on View:
#model DataModel
Class
public DataModel
{
public Contacts {get;set}
public Application {get;set;}
public Answers {get;set;}
}
Controller
DataModel model = new DataModel();
model.Contacts = items;
model.Application = item;
model.Answers= items;
return View(model);
View
#model DataModel
// will get all three tables data here
#Model.Contacts
#Model.Application
#Model.Answers
When I am in the View of a specific object, I can acces all the instances by this loop in the View:
#foreach (Reservation r in Model) { }
But How to implement the same foreach cycle with Ski Class, which is not associated with this View?
Add whatever you need access to to your model. It is common to create specific ViewModel classes that are specific to one or a few views and provide access to whatever they need. In your case it would have Reservations as well as Ski data.
Example:
public class ReservationViewModel
{
public List<Reservation> Reservations { get; set; }
public List<Ski> Skis { get; set; }
}
Now in the View you can foreach over Model.Reservations, as well as over Model.Skis.
I am having trouble figuring out how to return multiple variables to a view. Something like this. Can I get a little help?
public ActionResult CheatSheet()
{
var var1 = from ts in db.thisdatabase
select ts;
var var2 = from ls in db.thisdatabase
select ls;
var var3 = from d in db.thisdatabase
select d;
return View(var1,var2,var3);
}
Consider Using a ViewModel
You'll want to use a ViewModel to compose all of these different results and pass that model to the View:
public class ExampleViewModel
{
// Example collections for each of your types
public IEnumerable<Something> CollectionA { get; set; }
public IEnumerable<Something> CollectionB { get; set; }
public IEnumerable<Something> CollectionC { get; set; }
}
And then just use something like the following code to perform your specific queries and use the results of those queries to build your model and then pass it along to the View:
// Build the model
var model = new ExampleViewModel(){
// You'll likely want a .ToList() after these to ensure things work as expected
CollectionA = db.thisdatabase.Select(x => x.ts),
CollectionB = db.thisdatabase.Select(x => x.ts),
CollectionC = db.thisdatabase.Select(x => x.ts),
};
// Pass it to your View
return View(model);
Note: This assumes that you aren't actually querying the same exact table with each of your queries. If that was the case, then it may be more efficient to pull back a single collection with each of your properties and then assign your individual collections of properties to the model (instead of performing multiple, possibly redundant, queries.
Then within the View, you can reference the underlying property collections as expected and iterate through them or perform any other types of operations:
#model YourProject.ViewModels.ExampleViewModel
#foreach (var item in Model.CollectionA) { ... }
#foreach (var item in Model.CollectionB) { ... }
#foreach (var item in Model.CollectionC) { ... }
For More Complex Scenarios
If you didn't want to simply access a single column from your database but rather multiple, you'll likely want to create another model/class to map your properties and then store instances of those within your ViewModel.
Let's look at your example and see how that might work. So you currently are looking to store the ts, ls and d properties, so let's make a class to store those in:
public class Example
{
public string Ts { get; set; }
public string Ls { get; set; }
public string D { get; set; }
}
Now, when you perform your query, simply grab all of these and map them within a Select() call:
// This will now be an IEnumerable<Example>
var models = db.thisdatabase.Select(x => new Example()
{
Ts = x.ts,
Ls = x.ls,
D = d
});
You could now pass this along directly to your View if that's all that you needed:
// If you did this, you'd need to adjust your #model declaration
return View(model);
Or you could perform multiple of these if you needed to build different models for different tables and then compose all of those collections into a ViewModel similar to the original example:
var model = new ExampleViewModel(){
CollectionA = db.thisdatabase.Select(x => new Example(x)),
CollectionB = db.othertable.Select(x => new OtherExample(x)),
CollectionC = db.yetanother.Select(x => new LastExample(x))
};
Other Forms Of Storage
There are a few other approaches you could consider depending on your needs, such as using the ViewBag collection. The ViewBag is a dynamic collection that allows you to easily store and access objects within the View:
ViewBag.A = db.thisdatabase.Select(x => x.ts),
ViewBag.B = db.thisdatabase.Select(x => x.ts),
ViewBag.C = db.thisdatabase.Select(x => x.ts),
return View();
This will essentially work the same way, but instead of references #Model within your View, you would just use #ViewBag instead. It's also worth noting that this can also be used in conjunction with an actual model as well.
There are other approaches such as using the ViewData or Session collections, but you really should use a model. It's more in line with the actual MVC pattern, and if you get used to it, it should make your life much easier.
You can pass dynamic model in you view using ExpandoObject.
Example:
Controller:
public ExpandoObject ToExpando( object anonymousObject)
{
IDictionary<string, object> anonymousDictionary = new RouteValueDictionary(anonymousObject);
IDictionary<string, object> expando = new ExpandoObject();
foreach (var item in anonymousDictionary)
expando.Add(item);
return (ExpandoObject)expando;
}
public ActionResult CheatSheet()
{
var var1 = from ts in db.thisdatabase
select ts;
var var2 = from ls in db.thisdatabase
select ls;
var var3 = from d in db.thisdatabase
select d;
var model= ToExpando(new{ var1 =var1 ,var2 =var2 , var3 =var3})
return View(model);
}
View:
#foreach (var item in Model.var1 ) { ... }
#foreach (var item in Model.var2 ) { ... }
#foreach (var item in Model.var3 ) { ... }
I have a big problem and I'm a little bit disappointed. I can't find a good solution with this problem:
I have CompanyA and CompanyB who specialize Company who has an interface ICompany
in my controller. I then load from different databases, companyA and companyB in my List<company>. In my EditorView, I display the different objects companyA and companyB.
When I'm saving, in my controller, my objects in my list aren't to type CompanyA and CompanyB, but they are all of type Company.
How can I keep my types when I save?
Here is some code if my explanation is not clear:
My example CompanyViewModel.cs:
public class CompanyViewModel
{
#region Properties
public User User { get; set; }
public ExternalAccounts ExtAccounts { get; set; }
public List<Company> Companies { get; set; } // or List<object> Companies { get; set; }
....
#region Ctor
public CompanyViewModel()
{ }
public CompanyViewModel(ExternalAccounts extAccount, bool iniPrefLanguage = true)
{
//normaly it's load from bdd
...
Companies = new List<Company>();
if (test == true)
{
Companies.Add(new CompanyA()); // call webService
}
if (test2 == true)
{
Companies.Add(new CompanyB());
}
...
#region
}
OR I can have:
public ActionResult EditCompanies()
{
...
// Companies = new List<Company>();
Model.Companies.Add(new CompanyA()); // call webService
Model.Companies.Add(new CompanyB());
return View(Model);
}
public ActionResult SaveCompanies(ComapnyViewModel model)
{
var test = model.Companies.OfType<CompanyA>(); // return null !!!
test = model.Companies.OfType<CompanyB>(); // return null !!!!
test = model.Companies.OfType<Company>(); // return my objects !!!!
return View();
}
in view
#Html.EditorFor(m => m.Companies)
and i have EditorTemplate with Company.cshtml, CompanyA.cshtml, CompanyB.cshtml
During my load in View, each object in my list go to the right EditorTemplate (CompanyA and CompanyB)
But when i save... I have a list of company type only ...
Any ideas? Thank you!
What I did is:
I created a view with Company as model, and a partial view with CompanyA as model, and another view with CompanyB as model. Inside CompanyView, I called Html.Partial("CompanyAView", Model) and Html.Partial("CompanyBView", Model).
I hope this helps.
I am busy in my homecontroller.cs (in a MVC Razor project) where I send a class looking like the following one to my view:
private class Evt
{
public SEvent Event { get; set; }
public String Duration { get; set; }
};
public ActionResult Index()
{
List<SEvent> modFromWcf = proxy.GetAllEventsByPeriod(#System.DateTime.Now.Year, #System.DateTime.Now.Year + 1, "EN").ToList();
List<Evt> modTosend = new List<Evt>();
foreach (SEvent item in modFromWcf)
{
Evt ES = new Evt();
ES.Event = item;
ES.Duration = GetDuration(item.StartDate ,item.EndDate);
modTosend.Add(ES);
};
return View("Index", modTosend);
}
SEvent is just another class.
In my view I try to do something with some of the attributes, but I do not know how to retrieve the values of that class Event. This is my code:
#{
foreach (var item in ViewData.Model) {
string year = item.Event.StartDate.Year.ToString();
}
....
}
The error that I receive is: 'object' does not contain a definition for 'Event'. But I CAN debug and see that item DOES consist ofa class Event and a string Duration. I can see the contents too. Does somebody know how I can retrieve e.g. item.Event.StartData??
You need to explicitly define item.
ViewData.Model will return a collection of objects, and objects do not have Event properties.
Something like this should work:
#{
foreach (var item in ViewData.Model) {
if (item is Evt){
Evt itemEvt = (Evt)item;
string year = itemEvt.Event.StartDate.Year.ToString();
}
}
//...
}
Though I usually do something like:
#{
foreach (Evt item in ViewData.Model) {
string year = item.Event.StartDate.Year.ToString();
}
//....
}
You need to cast item to your class.
ViewData is of type ViewDataDictionary, which implements IDictionary<string, Object>, indicating that it is a dictionary matching keys of type string to values of type object.
Use this to make your code run as is:
#{
foreach (var item in ViewData.Model) {
string year = ((Evt)item).Event.StartDate.Year.ToString();
}
....
}
However, you should probably be using a strongly typed view for this instead of shoving data into ViewData for this.