I'm refactoring all my partial views to use the leading underscore naming convention (didn't know about this convention when I got started, don't want to deviate from such a plain convention). But I've come across the generated (razor, C#) "Error.cshtml" view in \Views\Shared and I noticed it looks like it may be a partial view (no html / body tags) yet doesn't follow the convention:
#model System.Web.Mvc.HandleErrorInfo
#{
ViewBag.Title = "Error";
}
<h2>
Sorry, an error occurred while processing your request.
</h2>
I also notice it doesn't specify a Layout, yet sets the ViewBag.Title property as if it were going to be used by a Layout. What's the deal?
Strange. My generated Error.cshtml looks like a "normal" view with HTML body:
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>Error</title>
</head>
<body>
<h2>
Sorry, an error occurred while processing your request.
</h2>
</body>
</html>
I think in your case the layout is not set to null, hence the default layout will be used that contains the HTML wrapping elements.
But it is still a "normal" view (not partial).
Related
HI read some articles about razorengine and I implemented the same.
https://antaris.github.io/RazorEngine/IntellisenseAndResharper.html
but it was not working for me.
even researched code from stackoverflow and try to work around it, but it was also not working.
Note: the answer is stackoverflow is not working for me
this is how I tried add intellisense to cshtml
#using RazorEngine
#using Text.Model
#inherits Templating.TemplateBase<EmailModel>
I had a model under folder Model with name EmailModel, I have a HTML template under Templates with name EmailTemplate
my model class
public class EmailModel
{
public string Timestamp { get; set; }
public string Name { get; set; }
}
my goal is to write in cshtml
#using RazorEngine
#using Text.Model<!-- namespace-->
#inherits Templating.TemplateBase<EmailModel>
<html>
<head></head>
<body>
<p>
#Model.Name
#Model.Timestamp
</p>
</body>
</html>
but still my intellisense is showing me squiggly lines #Model
but still my intellisense is showing me squiggly lines #Model
Shouldn't that be since you are referring to #Model as seen in below code segment but I don't see anywhere in your *.cshtml you are having a #Model binded. Basically your view is not a Strongly Typed View. So there is no model and thus the error
<p>
#Model.Name
#Model.Timestamp
</p>
#inherits is for inheriting a base class as the linked doc in your comment say
you can get minimal intellisense by providing your own base class and
using it with the #inherits directive.
You need to add the #Model directive to bind a model like
#model namespace.modelname
<html>
<head></head>
<body>
<p>
#Model.Name
#Model.Timestamp
</p>
</body>
</html>
For more information see Accessing Your Model's Data from a Controller
this is dll project so we cannot use #model to bind and get intellisense help in cshtml.
the appropriate solution to this in 2 ways
1) write a class and define a constant in that class
const string EmailTemplate =#"<html>
<p>
#model.Name is going to #model.Country
</p>
</html>";
call this constant into the class where you are calling razorengine
and pass this EmailTemplate as template for razorengine and you EmailModel as model
2)write in App.config under argumnets section
<arguments>
<add name="EmailBody" value="<html>
<body>
<p>
#Model.Name is going to
#Model.Country*********
</p>
</body>
</html>" />
<arguments/>
Note: html regular<> tags don't work in app.config
these two ways are working to make razorengine to create email templates in Non MVC (dll & console) applications
I'm learning ASP.NET MVC. I have a service folder where I have a class which reads data from an XML file. I've created a controller that I think (?) should work, and I'm attempting to create a view for this as well but for some reason I can't get intellisense to autocomplete the #model which makes me think I've done something wrong. Additionally, when I try access model properties from the view (eg Model.Description - if that is even the syntax?) I get numerous missing { and } errors. What am I doing wrong?
Controller:
public ActionResult Index()
{
NewsReader newsReader = new NewsReader(); //Read news from file
var newsItems = newsReader.GetNewsItems();
return View(newsItems);
}
And so far this is all I have for the view:
#Model IEnumerable<TestSite.Services.News.NewsItem>
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title></title>
</head>
<body>
<div>
<ul>
#foreach(Model.Description)
{
}
</ul>
</div>
</body>
</html>
Refer to #Erik Funkenbusch explanation of MVC #model meaning
The # sign is a directive to tell the Razor engine that what follows
is code, and it should compile that rather than simply write it to the
output.
so when you type
#model blah This is compiled by razor, and tells the Razor engine that
the type of the model is 'blah', so that when you use the keyword
Model (note the capital M and you would have to use the # sign as
well) it will refer to the model you have defined (in this case blah).
Therefore corrections should be taken as following:
//#Model IEnumerable<TestSite.Services.News.NewsItem>
#model IEnumerable<TestSite.Services.News.NewsItem>
//#foreach(Model.Description)
#foreach(var item in model.Description)
{
}
I recommend you to read Getting Started with ASP.NET MVC 5 to learn some basics about ASP.NET MVC 5. Razor engine is used by MVC 5 for the view styling.
And have some idea here
I have a regular application _Layout.cshtml and #RenderBody() to render all views inside, but only for the Login view need to be render as full page not inside #RenderBody().
Regards
You need to set the Layout property to null at the beginning of your view.
So, your Login.cshtml file should start with:
#model YourModel
#{
Layout = null;
}
You may not want to have no layout for your view. You probably want a custom layout (something like _LayoutFullPage.cshtml
<!DOCTYPE html>
<head>
<title>SOMETHING HERE ALONG WITH OTHER HEAD ATTRIBUTES</title>
</head>
<body>
#RenderBody()
</body>
</html>
and then use that layout in the view with
#{
Layout = "~/Views/Shared/_LayoutFullPage.cshtml";
}
Other options are to set the view as null in the cshtml (as suggested by RePierre) or to call return PartialView(model); within your controller.
In my MVC3 solution, I am attempting to implement the solution in this answer to dynamically add a CSS reference to the _Layout.cshtml file from within a partial view.
Here is a snippet of my _Layout file:
<!DOCTYPE html>
<html>
<head>
#Html.RenderStyles()
</head>
<body>
<div id="header-wrapper">
#Html.Action("Header", "Shared")
</div>
<div class="container">
#RenderBody()
</div>
#RenderSection("scripts", required: false)
</body>
</html>
and in the partial view (that is rendered by the #Html.Action("Header", "Shared") bit):
#{
Html.AddStyle(Model.Company.CSSPath);
}
While the HtmlExtension methods are working as expected, it seems that the events are occuring in the incorrect order.
The #Html.RenderStyles() in the _Layout head is occuring before the Partial View has time to add the CSS file to the Styles. I was under the impression that Partial Views were rendered before the _Layout.
I'm guessing that the cause has to do with the fact that I'm rendering my Partial View with an Html.Action call. If I don't do so, however, then how can I populate the Partial view with its desired model?
Per Matt Razza's comment, if I were to render the partial view the "normal way" using:
#Html.Partial("ViewName", model)
I'm then required to give my _Layout a Model and then force all other models to inherit from that Model? Is that truly the best option?
I have an MVC Masterpage.
Within the body, I have a placeholder for a title that all the views using this masterpage populate:
<asp:ContentPlaceHolder ID="TitleContent" runat="server" />
But as well as this title being used how it is, I want the exact same text to go in the title section of the head tag.
Of course, I could use another placeholder and make every single view specify the same content twice, but it would be better if some code could magically copy the literal text out of the placeholder and put it into the head title tag as well.
Obviously Javascriptis no use, because google wont process it to the page title. So I need to do this serverside.
In general, you would bind these values in the view to data either on a model or perhaps in a ViewBag (or ViewData for older versions of MVC) or something of that nature. So in your Layout (Master Page? Must be an older version of MVC?) you might have a couple of references to a ViewBag (or ViewData) value. Something like this:
<html>
<head>
<title><%= ViewBag.PageTitle %></title>
</head>
<body>
<div id="somePageTitle"><%= ViewBag.PageTitle %></div>
</body>
</html>
or:
<html>
<head>
<title><%= ViewData["PageTitle"] %></title>
</head>
<body>
<div id="somePageTitle"><%= ViewData["PageTitle"] %></div>
</body>
</html>
Then in your controller you would set that value as needed:
ViewBag.PageTitle = "This is a page title";
or:
ViewData["PageTitle"] = "This is a page title";
That would bind that value to both locations in the view. It's more common to use ViewBag (or other constructs, like ViewData and TempData, often depending on the MVC version being used) for elements in the layout (Master Page) and to use view models for elements in the specific view.
First off David's answer is right
Actual implementation would be whatever.master
<!DOCTYPE html>
<html>
<head>
<title><%= ViewData["Title"] %></title>
</head>
<body>
<asp:ContentPlaceHolder ID="TitleContent" runat="server"/>
</body>
</html>
In your View
<asp:Content ContentPlaceHolderID="TitleContent" runat="server">
<%= ViewData["Title"] %>
</asp:Content>
Change it in the controller
public ActionResult Index()
{
ViewData["Title"] = "My new title";
return View();
}
Or set it in the View itself
<script runat="server">
ViewData["Title"] = "My new title";
</script>
<asp:Content ContentPlaceHolderID="TitleContent" runat="server">
<%= ViewData["Title"] %>
</asp:Content>
Since these are variable, use them anywhere in your page you like
// These are the same
ViewData["Title"] = "My new title";
ViewBag.Title = "My new title";
// These are the same
<%= ViewData["Title"] %>
<%= ViewBag.Title %>
public Dictionary<string, object> ViewData
public dynamic ViewBag // .NET 4.0 +
Thanks for all your help.
I wanted to set the data in the view because I have different controllers using the same view, and also some controllers returning different views depending on the logic, so it made sense to define the page title on the view where it is a known entity, especially since it is usually not model data and is thus always a constant text for that page.
One complication, is that if the view was to be set as a dynamic piece of data taken from the model, that hadn't been calculated yet (such as a deferred execution iqueryable), then the masterpage never realizes the value unless you populate it in the view at a higher point in the page.
In other words, the view has to set the viewdata in script in a content placeholder ABOVE where it will be in the masterpage. You cannot set the viewdata[] property in the body content if the masterpage uses it in the head section.
This works:
<head>
<asp:Placeholder ID="HeadContent" runat="server"/>
<title><%: ViewData["PageTitle"] %></title>
</head>
<body>
<%: ViewData["PageTitle"] %>
</body>
Then in the view you can set the title:
<asp:Content ContentPlaceHolderID="HeadContent" runat="server">
<% ViewData["PageTitle"] = Model.SomeValueThatHasDefferedExecution; %>
</asp:Content>