I was wondering what, if there is one, is the best practice for including SEO content such as meta descriptions and keywords in an ASP.NET MVC (I'm using v3 RC) view. My initial plan is to create an actionfilter, applied globally to actions, to pull the relevant data from a data store and pass it as viewdata to the view.
My questions are:
1) Do you foresee any problems with this approach?
2) Are there any more suitable approaches?
3) what is an appropriate data store to use here - should i pull from the DB (or cache if the data is available), use resource files, config files, etc?
Thanks in advance,
JP
I would use attributes on my controller actions and add them to the ViewData
in my base controller in the method OnExecutingAction
.
The motivation to put it in the controller and not the view is that it's really more information about the actual action than about the view. And you can use it when returning different kinds of formats like json or xml.
Controller
class MyController
{
[MetaKeywords("hello,world,something,else")]
[MetaDescription("Tells you how to greet the world")]
ActionResult Hello()
{
return View();
}
}
You could always use a resource file instead of plain strings.
in base controller:
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
var keywords = filterContext.ActionDescriptor.GetCustomAttributes(typeof(MetaKeywordsAttribute), false);
if (keywords.Length == 1)
ViewData["MetaKeywords"] = keywords.Value;
var description = filterContext.ActionDescriptor.GetCustomAttributes(typeof(MetaDescriptionAttribute), false);
if (description.Length == 1)
ViewData["MetaDescription"] = description.Value;
base.OnActionExecuting(filterContext);
}
In your layout
<meta name="keywords" value="@View.MetaKeywords" />
And here is the answers your questions: =)
1) Do you foresee any problems with this approach?
Nope. It's a fine approach.
2) Are there any more suitable approaches?
Just gave you an alternative.
3) what is an appropriate data store to use here - should i pull from the DB (or cache if the data is available), use resource files, config files, etc?
I would put it in plain text (if you don't have to support multiple languages), else in a resource file. This information is typically not changed unless the view or controller is changed (where a recompilation is needed anyway). Hence no need for a more dynamic source.
Another approach would be to simply use in _Layout.cshtml:
<html>
<head>
<title>@ViewBag.Title</title>
<meta name="description" content="@ViewBag.MetaDescription" />
<meta name="keywords" content="@ViewBag.MetaKeywords" />
</head>
<body>
And in your views you cand define separately for each view the corresponding title/description/keywords:
For example in Home/Index.cshtml use:
@{
ViewBag.Title = "Home page title | samplePage.com";
ViewBag.MetaDescription = "Home page meta description";
ViewBag.MetaKeywords = "meta keywords keyword home page";
}
Add optional section to your layout page:
<!DOCTYPE html>
<html>
<head>
@RenderSection("ExtraHeadContent", required: false)
</head>
<body>
Now you can define meta tags on any content page using @section:
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
@section ExtraHeadContent {
<meta name="description" content="My super page">
}
<div>The main content</div>
See Optional Razor Sections with Default Content by Marcin Doboz.
If you are using a master page, you can create content placeholders to house the keywords and description, which you render on the view from data in the Model. The data in the Model can either come directly from a database field or from a helper that generates it based on other stuff!
Master Page:
<asp:contentplaceholder id="MetaTags" runat="server" />
View:
<asp:Content ID="Content1" ContentPlaceHolderID="MetaTags" runat="server">
<meta name="keywords" content="<%= Model.Keywords %>">
<meta name="description" content="<%= Model.Description %>">
</asp:Content>
1) Do you foresee any problems with this approach?
No.
2) Are there any more suitable approaches?
I would write a helper method for this or use a child action along with the Html.Action
helper because you will be pulling data from the database.
3) what is an appropriate data store to use here - should i pull from the DB (or cache if the data is available), use resource files, config files, etc?
This will depend on what your site is doing, how it is organized, where is the information stored, ...