What should i do for master page logic in mvc - asp.net-mvc

I m new in mvc. I had a web forms application and there was a masterpage of every page.
there was a virtual function in master page template and every page's page_load i was overriding it.
now i have mvc pattern in my project. where exactly should i put all these business in my project.

there are special views that can be used in MVC(assuming your are using razor).
There views are _viewstart and _layout(though can be named anything else).
so basically a _layout.cshtml view in a specific controller's views folder can work as a master page for the views existing in the same folder and a _layout.cshtml view in the shared folder can work as a master page for all the views present.
to specify to use a particular view as a masterpage use set the Layout variable inside the view. for ex Layout = "~/Views/Shared/_layout.cshtml";

Normally Master Pages goes in Shared folder in Views Folder.
I would recommend if you have multiple masterpages, try to minimize number for the same.
Make a parent Masterpage which should be called on all pages.
For using mutiple masterpages you can do something like this
<script language="C#" runat="server">
protected void Page_PreInit(object sender, EventArgs e)
{
if (User.IsInRole("Admin"))
{
this.MasterPageFile = "~/Views/Shared/Site2.Master";
}
else
{
this.MasterPageFile = "~/Views/Shared/Site.Master";
}
}
Also you can use
ViewMasterPage.MasterPageFile inbuilt class

Related

How can I reference a razor page's partial view from a MVC page?

How can I reference a razor page's partial view from a MVC page?
I have a controller that handles returning a lot of reporting related requests. For one particular report I want to reference a partial view in the same project but in a razor page's folder. I could easily copy it to the Report Controllers folder Reports/Views/Shared but for better organization I would like to keep it in my Razor page's shared views folder. I tried to reference the page exactly as a razor page would but it throws an error saying the view was not found even showing the location as I specified.
#await Html.PartialAsync("/Areas/MyRzrFolder/Views/Shared/_mypartial", Model)
Try adding the extension ".cshtml" at the end of the view path. This fixed it for me.
#await Html.PartialAsync("/Areas/MyRzrFolder/Views/Shared/_mypartial.cshtml", Model)

Casual layout patern in mvc with razor

I can't find the reel intentions behind MVC-Razor layouts through internet.
In shared folder, there is :
_Layout.cshtml
_LoginPartial.cshtml
Should i use the _Layout for pages that dosen't require to be logged in, and use _LoginPartial for pages that require to be logged in ? Or am i completely lost ?
To make it simple :
If i create a new view that can only be reached when logged in, should it be beginning with
Layout = "~/Views/Shared/_Layout.cshtml";
or
Layout = "~/Views/Shared/_LoginPartial.cshtml";
?
Edit :
Checking tutorials and explanation from everyone (thanks all)
_Layout.cshtml is exactly like a master page in WEB FORM,
So i should always use :
Layout = "~/Views/Shared/_Layout.cshtml";
at the begining of a page i want to have formated like others.
The Login partial can be applied after authentification to alter the layout (disconnect button instead of connect, ect.)
The file _Layout.cshtml represent the layout of each page in the application. While partial view is a custom, reusable component that you can use in each page you need it. For example, we can create a partial view for customer and call it many time in page
<table class="table table-condensed">
#foreach (var student in Model.Students)
{
#Html.Partial("_StudentForm ", student)
}
</table>
So _Layout is meant to be used for all pages and _LoginPartial.cshtml can be used inside the page you need to have a login form in. Check this article about partial view
Tips and Tricks about Razor Partial Views
Layout = "~/Views/Shared/_Layout.cshtml";
in your view start file (_ViewStart.cshtml), may times its the ONLY thing in that file.
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
the _Layout.cshtml and _Viewstart.cshtml combo is similar to a master page in web applications but these will not have controller actions associated with them. if you set the layout setting in the _ViewStart file you don't need to set it in your actual views, they will inherit it from the viewstart file.
If you look inside the layout file you will see this line somewhere
#RenderBody()
That is where your individual views HTML will end up when your specific view is called.
The Login partial is just a quick start to demonstrate a view that can change display based on if the user is logged in or not.
You can use the same _Layout.cshtml but your controller ActionMethod should change to Authenticate. Use the below link for more info.
Authenticate User in MVC
Its more of a naming convention for layouts.
views will inherit it from the viewstart file. If you look inside the layout file you will see the renderbody method.
#RenderBody()
This is where the HTML code is read and shown in the browser.
The same goes for the _loginPartial.cshtml its just there for looks and to show you what Mvc is capable of.
Visual Studio creates the layout _Layout.cshtml when all but
the Empty project template is used. This layout is applied to all views by default through the /Views/_ViewStart.cshtml file.
If you do not want the default layout applied to views, you can change the settings in _ViewStart.cshtml (or delete the file entirely) to specify another layout in the view, like this:
#{
Layout = "~/Views/Shared/MyLayout.cshtml";
}
Or you can disable any layout for a given view, like this:
#{
Layout = null;
}
Hope this helps.

Finding Razor partial views in the area EditorTemplates folder

I am starting to use EditorFor helper method to render my razor partial views, but I couldn't get the partials in the Areas folder to work.
Here is the path to the partial:
~\Areas\Products\Views\Shared\EditorTemplates\_Edit.cshtml
The partial is really simple with only one "div" tag to do the testing.
Try to use in my page view (~\Areas\Products\Views\EditPage.cshtml) as
#Html.EditorFor(m => m.ProductEditModel, "_Edit")
Visual studio tells me that "Cannot resolve template '_Edit'".
Now, if I move the partial to the root view folder:
~\Views\Shared\EditorTemplates\_Edit.cshtml
It works, Visual studio has no problems to resolve the template, and the div is renderred correctly in my browser.
I also tried to customize the RazorViewEngine, did not work either
namespace MySite.Web
{
public class RazorViewEngine : System.Web.Mvc.RazorViewEngine
{
public RazorViewEngine()
: this(null)
{
}
public RazorViewEngine(IViewPageActivator viewPageActivator)
: base(viewPageActivator)
{
AreaPartialViewLocationFormats = new[]
{
"~/Areas/{2}/Views/Shared/EditorTemplates/{0}.cshtml"
}.Union(AreaPartialViewLocationFormats).ToArray();
}
}
}
Just wondering what did I do wrong? BTW, I am using MVC3 at the moment, can't upgrate to MVC4 due to some old components.
When calling a partial view or view from a different area in MVC, specify the full path of the partial view or view. Since MVC is based on convention, by convention it will look in the same area the calling code in the view (or controller) resides for any partial views or views referenced, unless a specific path is used. Try using the full path to reference the partial view when it is located in the products area:
#Html.EditorFor(m => m.ProductEditModel, "~/Areas/Products/Views/Shared/EditorTemplates/_Edit.cshtml")
Since the view referenced is a shared view it doesn't matter if you specify the full path if you are in the same area. However, if you are trying to access a view within a different directory than the view trying to reference it and this directory is not named shared you will need to specify the full path regardless of area. It is similar when the controller calls the view; if a controller from the same area as the referenced view specifies the short name for the view and this view is from a parent directory named different than its own (ignoring the "controller" suffix) the view engine will not find your view. Unless of course the parent directory for the view is in the shared folder.
Whether it's in the controller or a view you can't use the "short name" across areas because the view engine has a convention for where to look when the path isn't used. Areas are meant to do this to keep your code separated, or decoupled if you will, at a high level by default. So any decision to "cross the barrier" should be thought about mindfully, but certainly not discouraged. It's all about convention.
I am answering my own question now.. My page view path was not correct. Since my area is Products, controller is ProductController, my page view should be placed in ~\Areas\Products\Views\Product\EditPage.cshtml, that way, it matches what the view engine expects, and the partial will be corrected resolved.

How do I pass a model to a partial view and load a specific record?

I am still relatively new to MVC and am finding every new concept to be a struggle, so please forgive me if this is an overly simple concept or the question has been asked many times before (I tried to find other examples).
I have several modals that can be called from my shared layout using jQuery's "dialog." Each modal is simply a DIV with a partial view attached to it like this:
<div id="JoinDialog" title="Join the Contractor Network" style="display: none;">
#Html.Partial("_JoinPartial")
</div>
And is called like this:
$(".ClickToJoin").click(function () {
$(function () {
$("#JoinDialog").dialog({ width: "auto", height: "auto"});
});
});
I have added a "Profile" modal to the layout in which I would like to insert the user's data into the INPUT values. To do that, I presume that I will need to pass in a model, and load the data I want via the controller. Since I currently have this partial view in the "Shared" folder, I assume I will also need to move it to one of my view folders where I can attach it to a controller?
Any nudge in the right direction would be appreciated.
Since I currently have this partial view in the "Shared" folder, I
assume I will also need to move it to one of my view folders where I
can attach it to a controller?
No there is no need for you to move the partial view to the controller folder. You can use the partial view from the shared folder itself (View Engine also looks at Shared folder to find a matching view). Here goes the sample example -
Lets say you have a model like this -
public class MyModel
{
public string Name { get; set; }
}
And then you have an action to return the partial view from the shared folder -
public ActionResult GetPartial()
{
MyModel model = new MyModel();
model.Name = "Rami";
return PartialView("TestPartial", model);
}
Then have the partial view in the Shared folder like this -
#model YouModelNamespace.MyModel
<div>#Model.Name</div>
Then on the actual page, you can have following code -
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#{
Html.RenderAction("GetPartial");
}
That will display the result from the partial view on the page as shown in below screenshot.
When you have to render a View (or a Partial View), asp.net mvc has some default orders to find it. First asp.net mvc will search the respective views' folder of the controller you are executing and if it was not found, asp.net mvc search on the Shared folder. So, if you have a view called _JoinPartial on the Views/Product (for sample) folder and shared folder, it will priorize the View folder. Sometimes you get a exception that views was not found, in there message you can see all places where asp.net mvc find it, for sample:
In your case, the controller could return a Partial View
public ActionResult GetJoinPartial()
{
return PartialView("_JoinPartial");
}
Since you have on the View folder, it will use it, instead it will use the partialView on the Shared folder.

ASP.NET MVC migrating master page - Problems with web control logic

I'm trying to migrate an existing ASP.NET Webforms 3.5 application into an ASP.NET MVC 3 application. That means, I attempt to convert existing .aspx pages with webcontrols and codebehind recpectively with controller logic and razor views.
At the moment I'm focusing on the master page (to get an analogue layout.cshtml for all other razor views).
For example I've replaced controls like asp:Menu, asp:LoginView with partial views and #Html.Action to invoke the controller action, run some code that has been in the codebehind of that masterpage before and return that partial view.
But now I'm getting lost with many web controls of the masterpage that have been set in/visible, depending on the code behind. For example there are two asp:panels in the master page that have been switched in/visible depending on the visited page.
The problem is that in razor views I don't have web controls and in controllers I cannot set attributes/properties (like private int counter;).
Thus I don't know how to carry on...
I hope you have got some ideas or experience with this situation.
Please ask if any information is missing.
You can either set properties of the Model or ViewData in the Controller and then use these in the Razor view with #if
e.g.
On the controller:
public ActionResult Index()
{
ViewBag.Foo = IsThisFoo();
View();
}
In the View:
#if (ViewBag.Foo) {
<p>This is foo</p>
}
else
{
<p>This is bar</p>
}
nb: best practice would be to do it as part of a strongly typed Model for the view

Resources