Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

asp.net mvc - different views need different meta tag in <head> inside layout page

I would like to stop a few of my pages from showing up in search results. My understanding is that I add the following to the <head> section of the page:

<meta name="robots" content="noindex,nofollow"/> 

The problem is that my pages use a common Layout page. Something like:

@{     Layout = "~/Views/Shared/_VanillaLayout.cshtml"; } 

Inside the layout page is the head section with a whole lot of links, scripts and meta tags. I don't want to duplicate this for indexable and non-indexable pages.

From my research I have found that: -

  • Having multiple <head> sections is bad.
  • Having the robot meta tag outside of head is bad.
  • Using robots.txt is more than I want and is bad.
  • Trying to pass a model into the layout is a bit of an overkill (need all models to inherit from some base and many pages are purely presentation and don't even have a model) and is bad.

Hopefully, I am missing something and there is a good (non-bad) way to do this or one of the approaches I have mentioned above is not so bad after all.

like image 903
acarlon Avatar asked Jan 08 '14 10:01

acarlon


People also ask

Does a meta tag have to be in the head?

<meta> tags always go inside the <head> element, and are typically used to specify character set, page description, keywords, author of the document, and viewport settings. Metadata will not be displayed on the page, but is machine parsable.

Can we have multiple _ViewStart in MVC?

We can also create multiple _ViewStart. cshtml pages. The file execution is dependent upon the location of the file within the folder hierarchy and the view being rendered. The MVC Runtime will first execute the code of the _ViewStart.

How do you specify a common layout for all views?

The default _ViewStart. cshtml is included in the Views folder. It can also be created in all other Views sub-folders. It is used to specify common settings for all the views under a folder and sub-folders where it is created.


2 Answers

It seems to me the easiest way would be to define a section in the <head> tag of your layout file that you can choose to populate with data in your views

<head>     <meta charset="utf-8" />     <title>@ViewBag.Title - My ASP.NET MVC Application</title>     <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />     <meta name="viewport" content="width=device-width" />     <!-- Adding a RenderSection here, mark it as not required-->     @RenderSection("AdditionalMeta", false)     @Styles.Render("~/Content/css") </head> 

Now, in any view in which you need to add additional meta data, simply add the following code at the end/beginning (after model declarations) of your view file

@section AdditionalMeta {     <meta name="robots" content="noindex,nofollow"/> } 

Since all of the Razor stuff is processed server side, there would be no issues in a) having JS append items given that some crawlers do not implement JS and b)no late appending to <head> tag/etc. Also, being marked as not required means that you only have to update the pages that you want to not be indexed and not have to set a variable on every single page in your application.

like image 139
Tommy Avatar answered Oct 11 '22 08:10

Tommy


You can add the following conditional with the meta-tag to the <head> element in your common layout:

<!DOCTYPE html> <html> <head>     <title>@ViewBag.Title</title>     @if (PageData["DisableIndexing"])     {         <meta name="robots" content="noindex,nofollow"/>       }         ... </head> <body>     ... </body> 

That flag will be set as disabled by default in your main _ViewStart.cshtml file, the one in the Views folder. That would mean by default no page will add that meta tag. This will be the _ViewStart file:

@{     Layout = "~/Views/Shared/_VanillaLayout.cshtml";     PageData["DisableIndexing"] = false; } 

Finally, on pages where you want to disable indexing you just need to override that flag. For example if the Foo view should not allow indexing, you would do:

@model MyNamespace.MyFooModel  @{     ViewBag.Title = "Foo";     PageData["DisableIndexing"] = true; } ... 

If all the views within a certain folder should disable indexing, you could even add another _ViewStart.cshtml file to that folder where you would just set PageData["DisableIndexing"] = true;

As a side note, you could also use the ViewBag to pass data from the _ViewStart to the layout, but code is a bit ugly as you don't have direct access to the ViewBag in the ViewStart. See this answer if you prefer to use the ViewBag.

like image 28
Daniel J.G. Avatar answered Oct 11 '22 07:10

Daniel J.G.