setting page html title from within an action - asp.net-mvc

How can I set the Html title from within a controllers action?

I don't believe there is a way to simply set the title directly from the controller with out setting up your views to accept some sort of data associated with the information. Especially since to actually set the title you'll need to output data in between tags.
That said, I'm sure there's something you could do to make this easier on yourself. I'm more or less just thinking aloud here, so I can't guarantee this will work. If I was sure that I would set my title's on every action that I have, then I would keep the title tags in the master page and create a custom attribute so you could do something like this:
[CustomTitleAttribute(Title = "Hello World")]
public ActionResult Index()
{
return View();
}
It would be up to you to implement the attribute and set up how you capture this information in the view and/or master page.
Generally speaking, since you may want the title to change on pages that have dynamic data, the above is probably not something you should do. Instead, just incorporate some way to determine the title you need in a view model. Maybe even a base view model that subsequent view models can inherit from.
public class BaseViewModel
{
public string PageTitle { get; set; }
public string PageDescription { get; set; }
//etc.
}
Then in the views you can do this, or even in your master page I think:
<title><%= Model.PageTitle %></title>
I think from a standpoint of separating concerns(which is kinda the whole point) that would be the best way to go.

It sounds not very wise for controller to control the output.
All a controller do, is to give viewdata to the output view and let the view determine what to do with it.
Please refer to the default ASP.net MVC template for how it is done.

Related

Need advice on how to structure asp mvc razor page

I have one page that will contain a lot data.
Outline of the page is on the image.
For output I have used "razor" engine.
Now I wonder will I get something if I refactor my code so each section
which data comes from database will be partial view?
On this page I need about 20 value objects to display all needed data.
I have made one "ViewModel" class that contains all data I need and set that
viewModel class as razor page model. Is this the right way how I should do this or
there is some smarter way?
public class MyViewModelClass{
public ValueObjectx x;
public ValueObjecty y;
public ValueObjectz z;
public List<ValueObjectT> tList;
public List<ValueObjectG> gList;
public List<ValueObjectS> sList;
}
In a scenario like this I would typically have each section as a partial view. Each section is responsible for it's own layout and ViewModel. This prevents the tendency to have a super view which has to know about too many things in order to render.
I would not use one ViewModel for all the data. I would only use the ViewModel for the data that might actually be posted back to the server. For all the other data, like lists, I would put it on the ViewBag. Like:
public ViewResult SomeAction()
{
var model = GetYourModelData();
ViewBag.TList = GetTList();
ViewBag.GList = GetGList();
ViewBag.SList = SList();
return View(model);
}
You could put all the lists in a separate helper object if you use them a lot.
Note that this is not a "this is how you should do it answer", it is more a description of what works for me. But as I see it the model of the view is one thing and the actual data, as data in drop downs etc., on the view is another thing and should be put in the ViewData property, but the ViewBag is just a dynamic wrapper around the ViewData property. You can then use the properties on the ViewBag as input to your partial views that should make up each of your sections.

Should a model contain all of the data required to build the view?

Lets say I have a site that has a Layout with navigation. This navigation is built each time a page is requested based on options the user has chosen. This navigation does not really have anything to do with the particular view being presented except that it is required for the Layout. The question is, should this be put in the ViewData or should the Model be required to inherit a NavigationModel?
ViewBag.NavItems = navItems;
or
public abstract class NavigationModel
{
public List<NavItem> NavItems { get; set;}
}
public class HomeModel : NavigationModel
{
}
This sounds like an ideal case to use Html.RenderAction inside of the view to render the navigation. This would call an action on a NavigationController that would be responsible for rendering the menu directly into the view.
Some MVC purists feel that Html.RenderAction breaks true MVC architecture; I see it as a way of delegating responsibility to render certain parts of the view that are not the primary responsibility of the "main" view that you're rendering.
Should a model contain all of the data required to build the view?
Absolutely and definitely YES.
The question is, should this be put in the ViewData
Absolutely and definitely NO.
You also have the possibility of using Html.Action and Html.RenderAction if this navigation widget could be considered as fully independent part of your site.

Problem with strongly typed partial view

I've a problem with Partial View.
I am developing a blog in asp.net mvc and I would make in my masterpage a list of categories, last post, last comments.
I think that the best solution is to use strongly typed partial view, and in each partial view pass the necessary model.
MY problem is that the model in View.. in any view (connected to the masterpage's contentplaceholder) enter in conflict with the models in partial views and I get an error like this:
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[Blog.Models.Articoli]' but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[Blog.Models.Categorie]'.
I found on web a dirty solution that consist of to pass togheter the model of any view, some viewdata, one for every model to pass in partial view. But this solution don't respect DRY Principle..because you must repeat this code for each action!
So, my question is: Can I create a model that contain also partial view's model?
If, yes, in that way?
It Exist another solution more simple?
Thanks for help
How about the View Model Pattern?
I've created wrapper classes that are passed to my views rather than whatever object I would normally use
public class MyCreateUserView
{
public User CreatingUser { get; set; }
public MyPartialViewObject Blah { get; set; }
}
In your view write:
public ActionResult CreateUser()
{
MyCreateUserView createUser = new MyCreateUserView()
{
CreatingUser = GetUserFromSomewhere(),
Blah = GetPartialViewObject();
}
return View(createUser);
}
Then your page header looks like so:
<%# Page Language="C#" Inherits="ViewPage<MyCreateUserView>" %>
and when you render your partial write:
<% Html.RenderPartial("../MyPartialViewObject ", Model.Blah); %>
Instead of solving that with the pattern you describe (which is generally a great pattern), I solve that with calls to RenderAction and have it return a partial view. That way the code is in one place as each call to each view does not have to worry about marshalling all the data you need. If you want to see a short discussion on how to use it, I would check Haack's blog here: http://haacked.com/archive/2009/11/18/aspnetmvc2-render-action.aspx. You can also check out the discussion on this other post here on SO: ASP.NET MVC Master Page Data

Asp.NET MVC View with different objects

If i have a controller action "Create" that returns a view with the following as the Model type:
public class PaymentModel
{
public Model.SummaryInformation SummaryInformation;
public Model.CardDetail CardDetail;
}
If there is a button on this view that POST's to an action "New" and I want that action to recieve a different object e.g.
public class PaymentNewModel
{
public Model.CardDetail CardDetail;
}
Is this possible? I do not want to use the same Model when the view is rendered to the Model that is POSTed
I'm not aware of anything that would prevent this. The action binder doesn't really care, as long as it can figure it out.
I assume the SummaryInformation object is only used for presentation? (it does not affect the input form?) In that case, you could pass it via ViewData and just bind the view directly against the CardDetail. This is closer to the MVC philosophy, but probably not a huge deal one way or the other.

Asp.net Mvc: Dynamic page title

in webforms I would always use my masterpage to set page titles and meta description based on the current url. I was thinking of doing the same for my Asp.net Mvc projects but I ain't sure where to start. It would be nice to be able to set the title/description based on the controller and/or action with some default values incase I don't specify any info. The reason why I do this is because I like everything to be in one place because that makes it easy to spot mistakes.
Edit:
After reading the answers and googling some I was thinking it might be cool to get the info from an xml file. With Xml looking something like this:
<website title="default title for webpage">
<controller name="HomeController" title="Default title for home controller">
<action name="Index" title="title for index action" />
</controller>
</website>
I am new to Asp.net Mvc so I am not sure where to initialize this.
I suggest the following strategy:
Create an hierarchy of models:
abstract class MasterModel
{
public string PageTitle { get; set; }
}
abstract class HomeBaseModel : MasterModel
{
PageTitle = "Home";
}
abstract class UsersBaseModel : MasterModel
{
PageTitle = "Users";
}
/************************************/
class HomeNewsModel : HomeBaseModel
{
PageTitle = "News";
}
class UsersProfileModel : UsersBaseModel
{
PageTitle = "Profile";
}
You define a master model to hold the page title and you create base models to hold default titles for a controller. This way, you can define the title in each action explicitly or leave it out so that the default title for this controller will be used.
Then in your master view you just write once:
<title><%= Model.PageTitle %></title>
and it's done.
You could simply pull that data from the master page's Model, then let that Model have some reasonable defaults.
So after a few days of trying stuff I ended up with making a custom filter that reads from a XML file.
I added the code to copypastecode.com
http://www.copypastecode.com/9797/
http://www.copypastecode.com/9809/
http://www.copypastecode.com/9805/
I am very novice at Asp.net Mvc and "real" C# coding so if you see strange stuff please forgive me. If somebody wants to optimize it or has a better solution feel free to post it as an answer.
Next thing I am gonna try is to make it without a filter so it's activated on all controllers. Not sure where to hook up the logic though. So if anybody can push me into the right direction let me know.

Resources