#model for _layout.cshtml on MVC4? - asp.net

I was wondering if there's a way to specify a model for the _layout.cshtml file, i've seen lots of posts with the basic same question with people replying with "alternative" solutions, not saying it's not possible nor showing how exactly we could achieve this
having some experience with webforms I've been trying to migrate to MVC and often find myself with such questions, I've found this website: http://blog.bitdiff.com/2012/05/sharing-common-view-model-data-in.html
which partially solved my problem but even them don't bind their _layout.cshtml with a #model, as far as I know, I have to specify a model on each view if I want to access the SharedContext, please correct if I'm wrong
what I wanted to do is declare a "#model Namespace.MyModel" on _layout.cshtml so it could retrieve its information by itself, instead of having to implement a model for each view inherinting from the LayoutModel
*I hope I'm being clear, basically, I wanted to know how can I declare #model tag on a _layout.cshtml so it can access its own model
with the solution I linked before (even though it's not linked to my question) I have to do:
#(((BaseController)ViewContext.Controller).Context.Property) to get the shared information, and if I could simply declare (and use) a #model instead, I could accomplish the same thing by doing something like: #Model.Property*
as you can see, im struggling trying to migrate whatever I already know from webforms to MVC and it's being quite difficult for me since I have to adopt certain practices which are completely different from what I'm used to
thanks in advance

You should delegate the parts of your layout that "need a model" to a separate controller using partial views and RenderAction:
#Html.RenderAction("SomeAction", "LayoutController")
Have LayoutController.SomeAction return a PartialViewResult, which you can then strongly type to a model.

Even though you already accepted an answer, based on your saying you are just pulling an image URL you should do it using JQuery, not a model.
This code is untested, apologies for that. Feel free to point out if I typed a bug. The HTML element containing the background image has the id="url" attribute so the selectors work.
Controller
[HttpGet]
public string GetSessionUrl()
{
//logic to detmine url
return url;
}
JQuery
$(document).ready(function () {
var $url = $('#url');
var options = {
url: "/Home/GetSessionUrl",
type: "get",
async:false
};
$.ajax(options).done(function (data) {
$url.attr('src', data);
});
});

You can add BaseModel to _Layout.
#model BaseModel
Then all models inherit from that BaseModel class.
public class MyModel : BaseModel
{
}
As others stated, it is not a good practice. If your model forgets to inherit from BaseModel, it'll throws exception at run time. However, it is up to you.

In BaseController you can declare any model as property.
public class BaseController : Controller
{
public BaseController ()
{
MyTag = new TagModel (); // or get db, take any value from there
}
public TagModel MyTag { get; set; }
}
In action:
ViewBag.MyTag = MyTag ;
And in _Layout.cshtml, you can use
#{
var myTag = (TagModel)ViewBag.MyTag;
}

Related

Spring MVC Model Attribute null

I want do add an ID to a URL in my template:
#Controller
public class DashboardController {
#RequestMapping("/dashboard")
public String index(Model model){
model.addAttribute("provider_id", "1");
return "dashboard";
}
}
In my dashboard.html I want do display the ID.
<a th:href="#{'/cloudservice/' + ${provider_id}}">Show</a>
But the Generated URL is /cloudservice/null. Why isn't the 1 displayed that i put into the model?
I tested this out and I couldn't recreate this issue, this is working perfectly fine for me. Please share the complete controller code and your dependencies here.
One wild guess, your Model class is of type org.springframework.ui.Model, right?
you can use like this http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#link-urls
<!-- Will produce '/gtvg/order/3/details' (plus rewriting) -->
view

How can I run code from my layout file?

I used the following tutorial to help me build an RSS Reader in my ASP.NET MVC3 Razor application:
http://weblogs.asp.net/jalpeshpvadgama/archive/2011/08/17/creating-basic-rss-reader-in-asp-net-mvc-3.aspx
However, unlike the tutorial example, I want the RSS feed to be displayed on every page, and have therefore added it to my layout file, /Views/Shared/_Layout.cshtml
I currently only have 2 views on my site, and to get the RSS Reader to work on both views I've got the following code in my HomeController:
public class HomeController : Controller
{
//
// GET: /Index/
public ActionResult Index()
{
return View(CT.Models.RssReader.GetRssFeed());
}
public ActionResult About()
{
return View(CT.Models.RssReader.GetRssFeed());
}
}
From my WebForms experience, I would simply add the RSS Reader code in my master page code behind, and it would automatically work on every page.
Is there a Controller for layout pages which allows me to do the same?
How can I get this to work on every call of the layout page, without having to return anything?
EDIT: Following #Sebastian's advice, I've now added this code to a Partial View, removed CT.Models.RssReader.GetRssFeed() from return View() and included this in my layout file:
#Html.Partial("_MyPartialView")
The code in this partial view is:
<ul>
#foreach (var item in Model)
{
<li>
#item.Title
</li>
}
</ul>
However, I'm not getting a runtime error:
Object reference not set to an instance of an object.
It's erroring on the line #foreach (var item in Model)
You have to create a partial view and add functionality there.
Then in your layout, render this partial.
EDIT
Is your partial view really a partial view? The reason I said that is because you have "_" in front of the name which suggests that it might be a layout (might just be a naming convention).
To fix object reference error, you have to add the #Model declaration on top of your partial view.
Hope it helps.
UPDATE
In order to use different model in partial view, you need to explicitly declare which model you are going to use on render partialmethod.
#{Html.RenderPartial("../YourFeed", Model.YourFeedModel);}
Let me know if that resolved your issue.
The new error you are having is due to you not passing a Model to the partial view. You can do this with the second argument of the Html.Partial function...
Html.Partial("ViewName", MyModel);
As I think you are trying to do this in a Layout page you could also consider using a static reference to get your RSS feed. So forget about needing to pass in a Model and in your partial have:
#foreach (var item in RssRepository.GetFeed())
{
<li>
#item.Title
</li>
}
this like to a class something like...
public static RssRepository
{
public static MyModel GetFeed()
{
return new MyModel();//<- return what you would normally pass as a Model for RSS feeds
}
}
Hope that all makes sense

How to create custom filter toolbar html helper in mvc3

I'm strugling on this for quite a while now. I need to create a custom mvc3 html helper for easy filter and toolbar management.
All that helper should look something like this below or something similar. What i want to do is to have a helper where i could give toolbar buttons and filter fields and it generate a toolbar and filter form for me.
I just can't figure it out, because i'm quite new in asp.net mvc
#Html.Toolbar(x => {
x.AddFilterButton();
x.AddButton("Naujas");
x.AddDropDownList();
},
#<text>
#Html.EditorFor(Model.ListFilter.Name)
Filter
ResetFilter
</text>,
filterVisible: false)
How i could achieve this? Any help would be highly apreciated. Thanks indeed.
Something like this:
public static class ToolbarExtensions {
public static Toolbar Toolbar<T>(this HtmlHelper<T> html) {
return new Toolbar();
}
}
public class Toolbar : IHtmlString {
public string ToHtmlString() { /* build your HTML off the state here */ }
public Toolbar AddButton(string label) {
/* build up state here */
return this;
}
}
The syntax on this would be a little different, instead of a lambda, would look like this:
#Html.Toolbar().AddButton("Button 1").AddButton("Button 2")
But you could easily change it to use a chaining object in the lambda instead of on the Toolbar method call.
The IHtmlString interface tells the ViewEngine to output the object as raw HTML when its encountered. The chaining is just achieved by returning the current instance in your methods after modifying the object state.

HTML.Partial - MVC 3 Razor

I have problem with returning a partial view from a controller with different model than my main View. For example:
public ActionResult Index()
{
//myModel - get Some Types
return View(mymodel);
}
public PartialViewResult Categories()
{
//my another Model - get different Types
return PartialView(myanothermodel);
}
And then in Index View:
#Html.RenderPartial("Categories")
I get an exception saying that it is of the wrong type. It expects first type(mymodel) instead of second type.
Is it possible to return different types for view and its partial view?
Thanks for response.
It looks like you're trying to render the action, not the view.
Call #Html.Action("Categories").
When you are using Partial View only use
#Html.Partial("Categories", Model)
or a especific Model with your own data
#Html.Partial("Categories", Model.Category)
I just understood a bit how partial view works. In your and my case actually, no need to define the Categories() action if you think the logic to get myanothermodel can be done in Index() action.
So I have mymodel.myanothermodel assigned in the Index() action and then in the strongly typed Index.cshtml I used this: (assume myanothermodel is Categories)
#{Html.RenderPartial("Categories", Model.Categories);}
alternatively:
#Html.Partial("Categories", Model.Categories)
Note that always use .RenderPartial() rather than .Partial() for best performance in .cshtml view. I used Model.Categories instead of mymodel.Categories because of the strongly typed Index.cshtml already have #model mymodel in the begining of the file.
In my practise I have the models like:
Model.Departments - IList<DepartmentModel>
Model.SelectedDepartment - DepartmentModel
Model.Employees - IList<EmployeeModel>
which is used in:
#{Html.RenderPartial("DepartmentMenu", Model.Departments);}
<div id="employeeViewContainner">
#foreach (var emp in Model.Employees)
{
Html.RenderPartial("CardView" + Model.SelectedDepartments.Name, emp);
}
</div>
This will render employee list with different skin for different department.

asp mvc controller creation

i want dynamically create ascx files, to partial render them.
but as i know, ot show them , i at least need dummy method:
public ActionResult test()
{
return PartialView();
}
how can i create this method for each new ascx file?
upd: i need factory?
Why would you create dynamic ascx files?
If you want to create all the layout in the controller you should be able to return it directly.
But then, why would you do that?
This way it will be really hard to do unit testing and refactoring and reuse.
You'd need to create your .ascx controls ahead of time. If you are doing this, I would recommend that you register a new view engine to provide a new PartialView location.
public class MyViewEngine : WebFormsViewEngine
{
public MyViewEngine()
{
PartialViewLocationFormats = new[]
{
"~/Views/{1}/{0}.ascx",
"~/Views/GeneratedControls/{0}.ascx",
"~/Views/Shared/{0}.ascx"
};
}
}
This allows you to write your dynamic views to the /Views/GeneratedControls/ folder. If you need to use a specifically named control (i.e. the control you generate has a random name) then you simply need to adjust your call to PartialView:
public ActionResult test()
{
return PartialView("name-of-control");
}
Otherwise MVC will use the name of the Action as the name of the control to use.

Resources