Dynamic Layout for Error View in ASP.Net MVC - asp.net-mvc-3

I have two action called "a" and "b". also I have two view for them. the layout of these views is difference.
for a:
#{
Layout = "~/Views/Shared/_X.cshtml";
}
for b:
#{
Layout = "~/Views/Shared/_Y.cshtml";
}
also the Error view is shared.
How can I use a dynamic layout for Error view. for example when an error occurred while processing action "a" the error show in layout of action "a" and if an error occurred while processing action "b" the error show in layout of action "b"?

You could write a helper method:
public static string GetLayout(this HtmlHelper htmlHelper)
{
var action = htmlHelper.ViewContext.RouteData.GetRequiredString("action");
if (string.Equals("a", action, StringComparison.OrdinalIgnoreCase))
{
return "~/Views/Shared/_X.cshtml";
}
else if (string.Equals("b", action, StringComparison.OrdinalIgnoreCase))
{
return "~/Views/Shared/_Y.cshtml";
}
return "~/Views/Shared/_Layout.cshtml";
}
and then:
#{
Layout = Html.GetLayout();
}

How about this overload?
Controller.View Method (String, String) (System.Web.Mvc)
in a action
return View(viewName,"_X");
in b action
return View(viewName,"_Y";

hope this help u....various way of rendering layouts in Asp.Net MVC.
Method 1 : Control Layouts rendering by using _ViewStart file in the root directory of the Views folder
We can change the default rendering of layouts with in _ViewStart file by using the below code:
#{
var controller = HttpContext.Current.Request.RequestContext.RouteData.Values["Controller"].ToString();
string layout = "";
if (controller == "Admin")
{
layout = "~/Views/Shared/_AdminLayout.cshtml";
}
else
{
layout = "~/Views/Shared/_Layout.cshtml";
}
Layout = layout;
}
Method 2 : Return Layout from ActionResult
We can also override the default layout rendering by returning the layout from the ActionResult by using the below code:
public ActionResult Index()
{
RegisterModel model = new RegisterModel();
//TO DO:
return View("Index", "_AdminLayout", model);
}
Method 3 : Define Layout with in each view on the top
We can also override the default layout rendering by defining the layout on the view by using the below code:
#{
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
thanks

You could try and pass the layout from the controller action: set the current layout in the session and then retrieve it in your error controller and pass it to the view through the ViewBag property:
public ActionResult A()
{
// Do things
// Set the layout
Session["currentLayout"] = "~/Views/Shared/_X.cshtml";
return View();
}
ErrorController:
public ActionResult NotFound() // 404
{
// Set the layout
ViewBag.ErrorLayout = Session["currentLayout"];
return View();
}
then in your error view:
#{
Layout = ViewBag.ErrorLayout;
}
I'll grant you this will not win a beauty prize; there might be other ways.
For example, take a look at this answer for how to set the layout in an ActionFilter: How to set a Razor layout in MVC via an attribute filter?
You could write your own Error Filter inheriting from HandleError and set the layout in there.

Related

Can i create KendoUI controls in my Controller

Can i create KendoUI ASP.NET MVC wrapper controls in my Controller class and pass them on to the views. And can i also display them there on the views.
for example:
public ActionResult Index()
{
GridBuilder<CustomerViewModel> grid
= new GridBuilder<CustomerViewModel>(new Grid<CustomerViewModel>(
new ViewContext(), // <-- view is empty
DI.Current.Resolve<IJavaScriptInitializer>(),
DI.Current.Resolve<IUrlGenerator>(),
DI.Current.Resolve<IGridHtmlBuilderFactory>()));
ViewBag.g = grid;
return View();
}
You could create a method that uses the kendo gridbuilder type:
public static Kendo.Mvc.UI.Fluent.GridBuilder<T> RenderGrid<T>(this HtmlHelper helper, string gridName)
where T : YourObject
{
return helper.Kendo().Grid<T>().Do stuff here;
}
And you would call it in your razor markup:
#RenderGrid("GridName")

How to access model data in parent partial view

I have one controller which will pass data to view Index.cshtml
public ActionResult Index()
{
var empId = #User.Identity.Name;
var empDetails = empRepository.GetEmployeeDetails(empId);
var emp = new UserViewModel {EmployeeDetail = empDetails};
return View(emp);
}
Layout of view Index.cshtml is Partialview _Layout.cshtml
#model HRM.Areas.EmployeeDetails.Models.UserViewModel
#{
ViewBag.Title = "Index";
Layout = "~/Areas/EmployeeDetails/Views/Shared/_Layout.cshtml";
}
<div>Hello</div>
I want to access the data which I passed from controller action to Index.cshtml in _Layout.cshtml.
Is there any way to do this ?
Your question is not clear on how you want to access the values so i'm making an assumption here:
If you want to include data from a view in a rendering from your layout page you can use the RenderSection method.
Layout Page:
#RenderSection("ViewSection", false)
View Page:
#section ViewSection {
<div>
<label>Emp Name:</label>
#model.EmpDetails.Name
</div>
}
When your Layout is rendered it'll look for a section in your view that matches and render it. Passing a false as the 2nd param tell the Layout that the section is not required.
For more info on this: http://weblogs.asp.net/scottgu/archive/2010/12/30/asp-net-mvc-3-layouts-and-sections-with-razor.aspx
Your question is not quite clear to me:/
My assumption ->
If you change your code to look like this:
public ActionResult Index()
{
var empId = #User.Identity.Name;
var empDetails = empRepository.GetEmployeeDetails(empId);
var emp = new UserViewModel { EmployeeDetail = empDetails };
ViewBag.UserViewModel = emp;
return View(emp);
}
on the Layout page you can access your data:
#if (ViewBag.UserViewModel != null)
{
//do sth with ViewBag.UserViewModel here
//for example:
#Html.Partial("_UserView",ViewBag.UserViewModel)
}
If you explain in details what you want to achive it will be easier for us to give you the right answer.
You can access the data in the model like this:
#Model.EmployeeDetail ...

How to set layout from controller

Is there a way to set the layout from the controller?
have tried:
ViewData["Layout"] = "..."
return View("view", Model);
I know it will sound odd with some people....
View method has overload to set its master layout something like this
return View ("NameOfView",masterName:"viewName");
In action method you can use MasterName property in ViewResult class to change layout page.
public ActionResult Index()
{
var myView = View();
myView.MasterName = "~/Views/Shared/_Layout2.cshtml";
return myView;
}
Using your code, you could put this in your View:
# {
Layout = ViewData["Layout"];
}
Daren Dimitrov has a very nice answer on this one with Attributes:
How do I specify different Layouts in the ASP.NET MVC 3 razor ViewStart file?
In the controller you can set a masterpage like this. I'm using MVC 5.2
return View("ViewName", "MasterPageName", model)
If you have a _ViewStart.cshtml file in your Views directory, you can automatically set the layout for all views within the same folder (and sub-folders):
#{
Layout = "~/Views/Shared/Layout.cshtml";
}

How do I insert a partial view in a View at a certain place in the view with MVC3?

I have an MVC3 application that I am implementing pjax into . Everything is working well except what to do on the server side when an address gets loaded that doesn't already have the main view on the client side. My Controller code looks like
public virtual ActionResult Details(Guid id)
{
var partDetail = new PartDetail(id);
var partialView = PartialView("Details", partDetail);
if(Request.Headers["X-PJAX"]!= null)
{
return partialView;
}
var mainView = View("Index");
// Stick Partial View into main view at #update_panel?
return mainView;
}
How can I stick the partial View into the main view so it inserts the partial view in the #update_panel?
Ok, without a major refactor, you could do the following.
(this assumes that you are able to set the #model on index.cshtml to PartDetail()).
in your controller action above, change:
var mainView = View("Index");
to:
var mainView = View("Index", partDetail);
then, inside your index.cshtml, add the following:
<div id="update_panel">#RenderPartial("Details", Model)</div>
As i said, this will ONLY work if the index #model is set to PartDetail(), otherwise, a little refactoring on the model in the index view will be required to include this PartDetail() model. this viewmodel might well look like the following:
public class IndexViewModel
{
ModelForIndex Index{get; set;}
PartDetail Details{get; set;}
}
this refactored viewmodel would be added to the index.cshtml as #model IndexViewModel and consumed by the partial as:
<div id="update_panel">#RenderPartial("Details", Model.Details)</div>
hope this makes sense.

How to pass variables across views and partial views in mvc 3?

I am creating a breadcrumb partial view which takes in a collection of title/URL. The collection will be generated in action methods and would have to be available on the breadcrumb partial view.
I tried couple of ways to get it done and this is one among such: http://goo.gl/rMFlp
But some how i could not get it working. All i get is an "Object reference not set to an instance of an object." Can you guys help me out?
{Updare}
Here is the code:
I created a Model class as follows
public class ShopModel
{
public Dictionary<string,string> Breadcrumb { get; set; }
}
Action Method
public ActionResult Index()
{
var breadcrumbCollection = new Dictionary<string,string>();
breadcrumbCollection.Add("/home","Home");
breadcrumbCollection.Add("/shop","Shop");
var model = new ShopModel() { Breadcrumb = breadcrumbCollection};
return View(model);
}
Model binding the view - Index
#Model NexCart.Model.Model.Custom.ShopModel
Finally here is the code on partial view:
<div>
#{
foreach (var item in #Model.Breadcrumb)
{
#item.Key
}
}
You haven't shown any code, so your question is impossible to answer. This being said here's how you could proceed. As always in an ASP.NET MVC application you start by defining a view model:
public class Breadcrumb
{
public string Title { get; set; }
public string Url { get; set; }
}
then you could write a controller action which will populate a collection of breadcrumbs and pass them to a partial view:
public class BreadcrumbController: Controller
{
public ActionResult Index()
{
// TODO: pull the breadcrumbs from somewhere instead of hardcoding them
var model = new[]
{
new Breadcrumb { Title = "Google", Url = "http://www.google.com/" },
new Breadcrumb { Title = "Yahoo", Url = "http://www.yahoo.com/" },
new Breadcrumb { Title = "Bing", Url = "http://www.bing.com/" },
};
return PartialView(model);
}
}
then you could have a corresponding partial view which will render this model (~/Views/Breadcrumb/Index.cshtml):
#model IEnumerable<Breadcrumb>
<ul>
#Html.DisplayForModel()
</ul>
and the corresponding display template (~/Views/Breadcrumb/DisplayTemplates/Breadcrumb.cshtml):
#model Breadcrumb
<li>
#Model.Title
</li>
Now all that's left is to include this child action somewhere using the Html.Action helper. For example you could do this in the _Layout if this breadcrumb is repeated on each page:
#Html.Action("Index", "Breadcrumb")
But obviously it could also be done in any view.

Resources