Asp.net mvc razor - Send data to main layout - asp.net

I am newbie in asp.net mvc.
I created an asp.net mvc4 empty application and added an entity model to it.
I have a layout page which I want to display menu categories,header,footer vb.But how can I send the data contains one more entity object(last posts,categories,tags) to layout page ?
Thanks

If you want to pass data (coming from database I assume) to the layout view you are facing a scenario where you have data that is passed to every page in your application. So what I would do is create a base controller from which all your controllers will inherit:
public class BaseController : Controller
{
public LayoutModel model;
public BaseController()
{
// Here you will use some business logic to populate your Layout Model
// You might also consider placing this model into the cache to prevent constant fetching of data from the database on each page request.
model = _service.Populate();
ViewBag.LayoutModel = model;
}
}
As you can see I used the constructor of the base controller to fetch the data needed for your layout view. I made a property named model and used some business logic method called Populate (you need to write this yourself) to populate the model variable. Then I place the model into the ViewBag.
Once I have this set up then every controller I make in my solution needs to inherit from the base controller:
public class HomeController : BaseController
{
// Controller code here...
}
which means that every controller can now access the model property from the base controller.
From here you can use the ViewBag.LayoutModel on each view like this (declare a local variable at the top of the view and cast it into the underlying type):
#{
LayoutModel MenuModel = ViewBag.LayoutModel;
}
and then use it like this:
#MenuModel.SomeProperty
This is just one of the ways to do it but there are other less/more complex ways. You need to do some research on your own and see which technique fits you the best...

Related

Clarity about helpers in MVC3?

Are helpers in MVC3 used in the controller as well as the views?
Is a helper the right place to put commonly used controller methods?
I want to create a common method to get all sub children IDs in a database and make sure it is in the right area. I just want to make sure I am putting my logic in the right area.
Thanks
You could implement a base Controller for that logic. Helpers, or extension methods, are good for when you don't want to change the interface for something.
The HtmlHelper is not available to the controller, because the controller should not be responsible for generating HTML, but the UrlHelper is available within the controller.
A method to get specific data from your database does not belong in your controller, or in a UrlHelper or an HtmlHelper. You should create a separate class for this logic, and then call the method on this class from within your controller. If you are using Dependency Injection, which I suggest, your controller code might look like this:
public class MyController
{
IMyDataUtil _dataUtil;
public MyController(IMyDataUtil dataUtil)
{
_dataUtil = dataUtil;
}
public ActionResult SomeAction(int parentId)
{
var childIds = _dataUtil.GetChildIds(parentId);
...
}
}
As you can see, this allows you to keep the data-access code in a class specifically designed for that purpose. The fact that this controller depends on that utility class is immediately obvious, and doesn't take that much more code than calling an extension method on a helper. Controllers that don't deal with that class's methods won't need to have it available.
On the other hand, if there are methods that are likely to be used by a bunch of different controllers, injecting this same data class into all of them may become cumbersome. In that case, you could:
Extend a base class that has an instance of the data-access class injected into it via method or property injection, and which then exposes it to sub-classes via a protected or public property, or
Create your own helper class that wraps the classes and methods you're likely to use in all your controllers, and inject that class so you only have one dependency for a variety of common functions, or
Combine steps 1 and 2.
If by "helpers" you're referring to things such as HtmlHelper then, no, these aren't used by the controller as in theory you could take your controllers and re-use them with an entirely different rendering engine (for example WPF) as the controller isn't responsible for rendering.
If you're talking about, as I think you are, helper classes/methods that manipulate your data ready for it to be put into a Model by a Controller and then handed off to a View for presentation, then you could consider a "business logic" layer. For example, if you were talking about (the ever typical) Bank Account example, you could have a:
public class BankAccountService
{
public IEnumerable<string> GetAllAccountIdsForCustomer(int customerId)
{
// Talk to the database here and retrieve the account id's for a customer
}
public string GetCustomerName(int customerId)
{
// Talk to the database here and retrieve the customer's name
}
}
Your controller would then:
public ActionResult AccountNumbers(int customerId)
{
var model = new AccountNumbersModel();
model.CustomerId = customerId;
model.AccountNumbers = BankAccountService.GetAllAccountIdsForCustomer(customerId);
return View(model);
}
Obviously in this example you'd need to have a class called AccountNumbersModel defined and you'd also probably want to consider using Dependency Injection to provide an instance of BankAccountService to your controller, but describing how to go about all that is kinda outside the scope of this answer.
The advantages this approach gives you are testability and separation, each piece of code is responsible for one task, and you reduce the complexity of each individual piece and make it easier to make changes without breaking things.
I want to create a common method to get all sub children IDs in a database and make sure it is in the right area. I just want to make sure I am putting my logic in the right area.
That sounds like a job for an ActionFilter.

Should each view model be handled by a single ViewModelLocator?

I am starting to explore the MVVM light and start to design my different viemModels. I have browsed for long time to find out what I am looking for but I could not get it :-(.
One sample I have is based on a single MainViewModel, which is handled inside a ModelViewLocator. In most cases we will have more than one viewModel, so should all viewModels be defined in a single ViewModelLocator file or do I have to have one ViewModelLocator per view?
In other words do I need to get this :
MainViewModel -> MainViewModelLocator
PictureViewModel -> PictureViewModelLocator
Ok fine but sill one question:
let say that I have 3 viewModels that I have create as ViewModel1, 2 and 3
In ViewModelLocation, I have create same structure as the MainViewModel in order to create the instance of it and have create a main property to access Models instance.
The problem I have found is that If each of my Views corresponding to each viewModels is set to is own datacontext as ViewModelLocator.ViewModelx, the view instance is create at design time and it makes me trouble if during the constructor of my view I need to call an external class which get data from a WCF service. It generate an "instance creation error".
In an other hand if in each view I bind then NOT from ViewModelLocator.ViewModelx but instead as directly ViewModelx then I do not get that error and works better.
So what is the properway to do and the logic path :
1 - Does the MainViewModel should create all other viewModel's ?
2 - Does each View must be bound to it's own MainStatic propery in ViewModelLocator ?
3 - Does each View create their own Instance of ViewModel ?
The way I have done is that my View which return service data from an external class during ViewModel constructor creation works only if I bind it directly to the ViewModel, does it have trouble doing it so ?
Usually there is no need for multiple view model locators. The common way is to create one ViewModelLocator which you then add to Application.Resources in App.xaml so it's available to be used anywhere in the application. Just create a property in the ViewModelLocator for each ViewModel you're using.
Below is an example which is using the IoC container in MVVM Light 4 (beta) to instantiate view models. You could also do without the IoC container but in more complex scenarios it'll definitely simplify your code:
public class ViewModelLocator
{
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<DetailsViewModel>();
}
public MainViewModel MainViewModel
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
public DetailsViewModel DetailsViewModel
{
get
{
return ServiceLocator.Current.GetInstance<DetailsViewModel>();
}
}
}

What's the best way to pass both a model and FormCollection data to my MVC 3 post controller

Normally, when receiving form data in a controller, I'd use:
public ActionResult Edit(int id, FormCollection formValues)
I have a view which is bound to a model but also includes some items not attached to the model which I thought I'd be able to access via FormCollection as
public ActionResult Edit(int id, MyModel objModel, FormCollection formValues)
I wondered if this is the best way to achieve this or if there's another to code this.
If this is a post, you will need to tag the method with the HttpPost attribute.
[HttpPost]
public ActionResult Edit(int id, FormCollection formValues)
{
var objModel = new MyModel();
// updates model here
TryUpdateModel(objModel);
}
In your view, you would have something like:
#model MyModel
... some html here
<fieldset>
<legend>MyModel Information</legend>
#Html.EditorForModel()
</fieldset>
So you can edit the model fields using the EditorForModel and retrieve those values using TryUpdateModel. Noting that you still have access to your FormCollection object.
This isn't the way to work. You shouldn't use your database model directly into your View.
You should pass a ViewModel. This way you can pass your model and extra properties.
public class MyViewModel
{
// All the properties for your model.
// All other properties needed and not attached to your model
}
In the Post action in your controller you can receive the MyViewModel and just make your model with the properties inside the ViewModel.
Check out this post for more information:
http://blogs.msdn.com/b/simonince/archive/2010/01/26/view-models-in-asp-net-mvc.aspx
Before you get any further, read about difference between a domain model and a view model. Quite often, in a simple application you can get away with using a domain model. As the system grows, you are likely to encounter problems where simple features will be difficult to implement. Eventually you'll see a need to refactor code and this is when you are likely to see a need for a view model.
Your question is regarding parameters that are passed to controller actions. You have a controller to edit something.
There is an Edit GET where you do something like this:
Read data from database
Wrap it into the object
Pass this object to a view which will display the object
There is an Edit POST want to recieve data and write changes to the database. So what do you need to make that happen? You need id and a combination of fields that you wish to update. Passing FormCollection and something else means that you have to map values from FormCollection to your domain model. This is time consuming and a repetative task.
You don't want to do this, so you want submit back a single object, doesn't matter whether it's a view model or a domain model, but it should be an object that contains all the data that you need for an update.
Data binding feature of the MVC 3 framework will automatically map fields from the form to your model using clever reflection.
What you are doing is kind of works and it's a great way to learn. So don't give up. Refactor, see whether you can pass a single object and work with that.
Good luck

Binding Model properties directly in View

I've found this text in Prism documentation. I'm starting on MVVM and I'm at lost. Can (should) I bind model properties in the view or I must create a viewmodel with a proxy property for every property in the model?
The model classes typically provide
property and collection change
notification events through the
INotifyPropertyChanged and
INotifyCollectionChanged interfaces.
This allows them to be easily data
bound in the view. Model classes that
represent collections of objects
typically derive from the
ObservableCollection class.
EDIT: Here is some extra info to help. I'm building a personal project from the ground up (so I'm designing the models too), this is the first time that I use MVVM and I want to learn properly.
My model is very hieraquical, having classes with list of more class with more list inside, building a complex tree of information. I was trying the "standard" MVVM approach, build the model with POCO and no notifications, and using List. Then building the ViewModel with proper notifications and using ObservableCollections.
The problem is, the way it is going, I'm almost reconstructing my whole model as a ViewModel AND having to keep the data synched between the to (the ObservableCollection to the List). Then I read that on the Prism docs and wondered if I should have all that trouble or just create a root ViewModel for logic and bind all the rest to the model itself.
It depends really, if your model already implements INotifyPropertyChanged and/or IError info you might want to bind right to the model property. However if you want to do special validation and other stuff that the model knows nothing about you add the property wrappers in your view model.
This article gives a good example of a hybrid: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
Often my MV properties look like this and thats quite normal:
public string Symbol
{
get { return Model.Symbol; }
set { Model.Symbol = value; this.NotifyOfPropertyChange(() => this.Symbol); }
}
I often do NOT implement INotifyPropertyChanged in the model and thus often I have to write the wrappers.
EDIT: In response to your additional information: It can be a bit tricky to to keep the collections and lists in sync. In your case what I would do is to create a view model for each model class, but NOT wrap all the properties just access them like this: {Bindng Customer.Name}. But of course you have to create a wrapper for the collections which contain view models. The Prism documentation is, as they say themselves, just guidance, if your scenario needs a different approach then this is fine.
Take a look at this code. I only wrap the collections and the properties I will access through the model. This gives you the best of both worlds. Then IF you need a special property that does not belong into you model you can add it to the view model (see the CustomerViewModel), or if you need special notification for a certain properties.
class CompanyViewModel{
public CopanyViewModel(Company c){
foreach(var customer in c.Customers)
Customers.Add(new CustomerViewModel(customer);
}
public Company Company {get;set;}
public ObservableCollection<CustomerViewModel> Customers {get;set;}
}
class CustomerViewModel{
public CustomerViewModel(Customer c){
Customer = c;
}
public Customer Customer {get;set;}
public Brush CustomerBackground{
get{
if(Customer.Active)
return Brush.Greeen;
else
return Brush.Red;
}
}
}
(This code might not work, I just typed it in here.)
Now, if you need changed notification for all models and all properties you have to either implement it in you model or in wrap all properties in a view model.

Multiple models sent to a single view instance

My terminology is probably way off here but basically I'm trying to pass multiple data models to a view. To help put the question in context, take this example:
Say I was making a blog. When I log in I want the home screen to display a list of all new unapproved comments, as well as a list of recently registered users, and a list of the most recently submitted blog posts.
Most discussions I've seen suggest strongly-typing the view page so it can be called with something like "return View(RecentComments)" and iterate through the comments in the view, or to cast the data model like "var NewUsers = (MembershipUserCollection) ViewData.Model". What I'm ideally after is the 'right', or at least a 'right-enough', way of passing multiple models while still maintaining appropriate logic separation.
One way is to create a new type that encapsulates both pieces of model data:
public class MyBigViewData {
public SubData1 SubData1 { get; set; }
public SubData2 SubData2 { get; set; }
}
public class SubData1 {
... more properties here ...
}
public class SubData2 {
... more properties here ...
}
Another way is to store the "main" model data as the strongly-typed data and store other data in the view data as dictionary items:
ViewData["username"] = "joe"; // "other" data
ViewData["something"] = "whatever"; // "other" data
ViewData["subdata1"] = new SubData1(...);
return View(myRealModelData);
The advantage of the second approach is that you don't need to do anything special at all: It works right out of the box.
What I've done in the past is written a class that contained instances of both the classes I will need on the view.
ie
public class City{
public Mall TheMall;
public School TheSchool;
}
Then your view will be strongly typed as City, and you will use Model.TheMall.Property and Model.TheSchool.Property to access what you need
EDIT
This is an example of what other posters mean by creating an object with both objects as fields/properties
Sadly, the only way to accomplish passing multiple objects is either by creating an object with both objects as fields/properties, or by using a weakly typed array.
The way to pass multiple models to a view is to create what we call a Form View Model which has your other models within it.
Then in your view you can pass the individual models contained in your Form View Model to the Partial Views responsible for rendering the data in said models.
Makes sense?
edit
btw: a form view model is simply a class. it's not a special type as may have been suggested by my answer.
In addition to my other answer, another way to do this would be not to strongly-type the view and master pages in the page directive, but instead make use of the generic type-based ViewData extensions from MVC Contrib. These extensions basically use the fully-qualified type name as the ViewData dictionary key. Effectively, the typing benefits are the same as the strongly-typed page approach, with less class overhead in terms of the number of view model classes required. Then in your actions you do
ViewData.Add<Car>(car);
ViewData.Add<LayoutAData>(layoutAData);
and in the views you do
<%= ViewData.Get<Car>().Color %>
and in the master page you do
<%= ViewData.Get<LayoutAData>().Username %>
You could cache these Get<> calls inline in the views to mitigate the cost of casting multiple times.
After working on a large ASP.NET MVC app, I found the approach that was most productive while minimizing runtime casting was based on using generics to mimic the nested structure of views. Essentially views get their own data type. Typically these are either domain objects, or collections of domain objects that include metadata. Generic versions of these types are available across all possible master pages, taking a type parameter that defines data relevant to the master page.
public class Car {
// can be used as a model
}
public class CarCollection: Collection<Car> {
public BodyTypes BodyType {get;set;}
public Colors Color {get;set;}
// can also be used as a model
}
public interface ILayoutModel<TLayout> {
TLayout LayoutModel {get;set;}
}
public class CarView<TLayout>: Car, ILayoutModel<TLayout> {
// model that can be used with strongly-typed master page
}
public class CarCollection<TLayout> : CarCollection, ILayoutModel<TLayout> {
// model that can be used with strongly-typed master page
}
public class LayoutAData {
// model for LayoutA.master
}
public class LayoutBData {
// model for LayoutB.master
}
It's also possible to invert the generic-ness, but since the view dictates the layout, the view data should dominate over the layout data in my opinion. LayoutA.master would derive from ViewMasterPage<ILayoutModel<LayoutAData>> and LayoutB.master would derive from ViewMasterPage<ILayoutModel<LayoutBData>>. This keeps the view data and the layout data separate, in a consistent, strongly-typed and flexible way.
Creating an object that can encapsulate your other objects is the best way to go. Otherwise you're stuck with a bunch of ugly ViewData tags in the controller and the view.
One thing no one seems to have mentioned is that in the original questioners example, it might make sense to create the view out of a series of child actions that handle their own area of functionality rather than making a mega view model. That way the components such as unnapproved messages etc can be reused.
This also gives better encapsulation.

Resources