How can I run code from my layout file? - asp.net

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

Related

how to insert partial view from another controller in asp.net mvc 5

I want to insert a partial view from NewsController into HomeController.
In my NewsController
public ActionResult LastNewsPatial()
{
var lstLastNews = db.Articles.Take(5).OrderByDescending(m => m.CreatedDate).ToList();
return PartialView(lstLastNews);
}
In Views/News folder i create LastNewsPatial.cshtml
#model IEnumerable<mytest.com.Models.Article>
#foreach (var item in Model) {
<div class="glidecontent">
<img src="#item.ImageURL" style="float: left; margin-right:21px;" />
<strong>#item.Title</strong><br /><br />
#item.Content
</div>
}
In Views/Home/Index.cshtml i insert a LastNewsPatial view
#Html.Partial("~/Views/News/LastNewsPatial.cshtml")
When i run my project then I received a error
Object reference not set to an instance of an object.
at row
#foreach (var item in Model)
in LastNewsPatial.cshtml
How can I fix it?
The reason for your error is that the Model isn't passed to the view... infact the action isn't even called at all. Set a breakpoint and you'll confirm this.
I think you should be calling #Html.RenderAction inside the index instead of #Html.Partial.
Instead of #Html.Partial("~/Views/News/LastNewsPatial.cshtml")
use
#Html.RenderAction("LastNewsPatial","News")
or #Html.Action("LastNewsPatial","News")
You don't need to give .cshtml in name of view when rendering a view. Only give name of PartialView without .cshtml like this.
#Html.Partial("~/Views/Shared/LastNewsPatial")
You can also use #Html.Action() to render your view like this
#Html.Action("LastNewsPatial","News")
This worked for me: #Html.Partial("../Views/Shared/LastNewsPatial")
The .. instead of the ~
Some of the answers here are missing the question
You use this
#Html.Partial("~/Views/News/LastNewsPatial.cshtml")
Which creates a partial view without a model. So in order for this to work you need to pass model.
#Html.Partial("~/Views/News/LastNewsPatial.cshtml", your_model)
Your problem is not view related and you simply pass no object to the partial. How to do it is up to you. Do you want a Html.Partial or Html.Action? Depending on your needs.
P.S.
Use RenderPartial and RederAction they are better practices since Partial and Action return an HTML string where instead using render allows ASP.NET to write directly to the response stream.

Dynamic Menu Layout in ASP.NET

I am trying to create a dynamic menu layout in ASP.NET MVC 4. What I did is in my shared view I have the following call
#{ Html.RenderAction("Index", "FooterMenu"); }
I have a controller, and a view for my FooterMenu. It also have a model. Now i try to call it however I keep getting this error
System.StackOverflowException was unhandled
Its keep pointing to my index
public ActionResult Index()
{
return View(db.FooterMenus.ToList());
}
It also say make sure i am not in an infinite loop, or recursion. But my code is fairly simple
I would suspect that you want to return a PartialView - so that the menu doesn't also render the layout, which renders the menu, which renders the layout, which renders the menu...etc
public ActionResult Index()
{
return PartialView(db.FooterMenus.ToList());
}
I believe you are caught in a recursive loop. My guess is that the Index view in FooterMenu is using the shared view, which itself is calling #{ Html.RenderAction("Index", "FooterMenu"); }

ASP.NET MVC 3 Partial View in layout page

I'm working on setting up a shared content (navigation) for an asp.net MVC layout page.
Here is my partial view "_LayoutPartial.cshtml" with code to pull navigation data from a model.
#model MyApp.Models.ViewModel.LayoutViewModel
<p>
#foreach (var item in Model.navHeader)
{
//Test dump of navigation data
#Html.Encode(item.Name);
#Html.Encode(item.URL);
}
</p>
Here is how the code for my controller "LayoutController.cs" looks like.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MyApp.Models.ViewModel;
namespace MyApp.Controllers
{
public class LayoutController : Controller
{
//
// GET: /Layout/
LayoutViewModel layout = new LayoutViewModel();
public ActionResult Index()
{
return View(layout);
}
}
}
Here is the code for the "_Layout.cshtml" page. I'm attempting to call the partial view here using Html.RenderAction(Action,Controller) method.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<p>
#{Html.RenderAction("Index","Layout");}
</p>
#RenderBody()
</body>
</html>
When the layout page executes the #{Html.RenderAction("Index","Layout");} line, it throws out an error message "Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'."
What am I missing friends? How can I call a partial view in a layout page?
Thank you all in advance!
Instead of:
public ActionResult Index()
{
return View(layout);
}
do:
public ActionResult Index()
{
return PartialView(layout);
}
If you don't do that when you return a normal view from your child action, this normal view attempts to include the Layout, which in turn attempts to render the child action, which in turn returns a view, which in turn includes the Layout, which in turn attempts to render the child action, ... and we end up with names like the one ported by this very same site.
Also in your partial you don't need to do double encoding. The # Razor function already does HTML encode:
#model MyApp.Models.ViewModel.LayoutViewModel
<p>
#foreach (var item in Model.navHeader)
{
#item.Name
#item.URL
}
</p>
First verify that your child view is inside the Shared directory
#Html.Partial("_LayoutPartial")
OR
#{Html.RenderAction("actionname", "controller name");}
And don't use #Html.Encode(), Razor is already doing for u. Just use
#item.Name
#item.URL
I have solved this error getting on Layout page
System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper
Important !
First create partial view inside shared folder
In Controller ,
public PartialViewResult Userdetails()
{
....
return PartialView("PartialViewName", obj);
}
In Layout Page,
#{Html.RenderAction("action","controller");}
I know this is an old question but I thought I would throw this in here. You can use either Html.Action or Html.RenderAction. They both technically do the same thing but depending on how much content you're returning back can have an impact on which one you should really use for best efficiency.
Both of the methods allow you to call into an action method from a view and output the results of the action in place within the view. The difference between the two is that Html.RenderAction will render the result directly to the Response (which is more efficient if the action returns a large amount of HTML) whereas Html.Action returns a string with the result.
Source

Why is my validation firing on the get request before the post in MVC3?

I have a MVC3 view that enables the user to create a couple different things. Within the parent view the forms to do so are broken up via jquery ui tabs like the following:
<div id="tabs">
<ul>
<li>New Thing 1</li>
<li>Different New Thing</li>
</ul>
<div id="tabs-1">#Html.Action("CreateNewThing", "NewThingController")</div>
<div id="tabs-2">#Html.Action("CreateDifferentThing", "DifferentThing")</div>
<div></div>
</div>
<script type="text/javascript">
$(function () {
$("#tabs").tabs();
});
</script>
Within the partial view I have:
#model NewThingViewModel
#using (Html.BeginForm("CreateNewThing", "NewThingController", FormMethod.Post, new { id = "frmCreateNewThing" }))
{
...
with input fields, a submit button, etc. This seems to work well: it renders everything and posts just fine to the right controller action method.
However I'm now wiring in the validation and I've got an issue.
In the controller it is rendering the view like so:
public ActionResult CreateNewThing(NewThingViewModel model)
{
... initializing model fields, drop downs etc.
return PartialView("CreateNewThing", model);
}
I have a seperate post method like so:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateNewThing(NewThingViewModel newThingViewModel, FormCollection collection)
{
.....
}
Sample Model:
public class NewThingViewModel
{
[Required]
[StringLength(50)]
[Display(Name = "Display Name:")]
public string DisplayName { get; set; }
}
The trouble is, when the page first comes up the fields marked as [Required] through DataAnnotations in the model are showing up red as well as the validation summary showing them invalid when the page initially shows. I.E. it's acting like it's already been posted before the user gets to enter anything on the initial load or even put anything in the text boxes.
I know the first non-post CreateNewThing is firing because I can catch it in the debugger and I know the 2nd one does not on the initial load.
What would cause my validations to fire on the Get?
Is it due to the way Html.Action works and the fact that I'm rendering partial views onto another view?
I'm using UnobtrusiveJavaScriptEnabled and ClientValidationEnabled = true in web.config.
I can't find anyone else that has run into this particular problem. Every other example just seems to work, then again I don't find an example where the view is broken into three partials contained within jquery ui tabs.
How do I fix this?
Options:
Do I need to manually manipulate the Model.IsValid as a workaround?
Use a different mechanism to render the partial views on the parent view instead of Html.Action?
Use some javascript/jquery to catch the validation and stop it?
Don't have method parameters on your GET controller action. You can initialize an empty model and pass it to the view but you dont need a model to be passed into the method
You're passing in an "empty" model (which I assume has default values set for your required properties), when you should be passing in null.

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.

Resources