ASP.NET MVC partial view that updates without controller - asp.net-mvc

I have a partial view that shows a list of Categories. I'd like to put that partial view on any page, but I'd like to have it to call to the service and get a list of categories by itself without me having to do that in every controller action. Something like webforms in which you can put a code-behind on it.
For eg.
Actions
public ActionResult Index()
{
JobListViewModel model = new JobListViewModel();
model.Categories= jobService.GetCategories();
return View(model);
}
public ActionResult Details(int id)
{
Job job = jobService.GetJob(id);
return View(job);
}
I created a partial that will take the model.Categories model and display a list. As you can see, the Index page will work fine, but I do not want to call it again in the Details page. Is there a way to make my partialview call to the GetCategories() service by itself?

Use Html.RenderAction - that gives the partial view its own controller action.

You should also mark you partial action with the attribute [ChildActionOnly].

DVark,
As noted in the accepted answer, for your scenario, RenderAction is the most appropriate.
I thought I'd link a little article that distils my thinking on the topic (i.e. when to use RenderPartial vs RenderAction):
http://cbertolasio.wordpress.com/2010/09/21/mvc-html-renderaction-vs-html-renderpartial/
hope it helps
[edit] - as an aside. a year or so ago, i got myself into a few scrapes by not appreciating the power of RenderAction, in favour of RenderPartial. as a result, i had littered the shared view space with lots of partialviews in order to access them from a variety of sources. the moral of the story: know your 'territory' before planting your flag.

Related

MVC RenderAction return only renders partial part

I have this contact form which I want to use on two pages (two views) in MVC 5.x (razor viewengine) So I have put the form in an partialview called _Contact and I have read that RenderAction is the best approach if you do not have the required data for the partialview in your model and if it is more standalone (seperate from the rest of the view)
So I call it like this:
#{ Html.RenderAction("SendMail", "Uk");}
My Uk controller has these two methods:
[HttpGet]
public PartialViewResult SendMail()
{
return PartialView("_Contact");
}
[HttpPost]
public PartialViewResult SendMail(FormCollection fc)
{
// send mail using values out of the form (sorry did not feel like building a complete model for it
ViewBag.Succeed = true;
// if smtpclient could not reach server etc. it returns false
return PartialView("_Contact");
}
it all works, but the PartialView is only rendered, not on the placeholder where i call the RenderAction. It works all great, but after the post it just displays the partial view and not the "parent view" and the shared layout view etc. I hope that I made myself clear. Please let me know if I need to add more info.
This is the BeginForm from my shared view:
using (Html.BeginForm("SendMail", "Uk", FormMethod.Post))
It will not work as expected for your current code, because when you post the form, it returns Partial View not complete View. If you want to get only partial view then you have to submit your form via Ajax.
In ajax's success handler you will get HTML of your partial view and that you can put in a DIV tag of partial view container.
This link will give you a better idea about Posting Partial View via Ajax.
ASP.NET MVC Partial view ajax post?

Can I share the same view for a create and edit in MVC3

I have a fairly complex view that's almost the same for the create and edit functionality in MVC3.
Every time I change one I have to remember to make the same changes in the other.
Is there a way that I can share a view between create and edit. For example can I have two view files with different names and link them or is there another even better way.
thanks
Marcel
You could simply make a partial view with your form contents and include this partial view in your create and edit view. With that, you you are able the have some differences in your views (maybe headline "edit" / "create").
#Html.Partial("FormView")
On the other side, you could specify your view in your controller action.
public ActionResult Create()
{
return View("CreateEditView");
}
public ActionResult Edit()
{
return View("CreateEditView");
}

Problem with strongly typed partial view

I've a problem with Partial View.
I am developing a blog in asp.net mvc and I would make in my masterpage a list of categories, last post, last comments.
I think that the best solution is to use strongly typed partial view, and in each partial view pass the necessary model.
MY problem is that the model in View.. in any view (connected to the masterpage's contentplaceholder) enter in conflict with the models in partial views and I get an error like this:
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[Blog.Models.Articoli]' but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[Blog.Models.Categorie]'.
I found on web a dirty solution that consist of to pass togheter the model of any view, some viewdata, one for every model to pass in partial view. But this solution don't respect DRY Principle..because you must repeat this code for each action!
So, my question is: Can I create a model that contain also partial view's model?
If, yes, in that way?
It Exist another solution more simple?
Thanks for help
How about the View Model Pattern?
I've created wrapper classes that are passed to my views rather than whatever object I would normally use
public class MyCreateUserView
{
public User CreatingUser { get; set; }
public MyPartialViewObject Blah { get; set; }
}
In your view write:
public ActionResult CreateUser()
{
MyCreateUserView createUser = new MyCreateUserView()
{
CreatingUser = GetUserFromSomewhere(),
Blah = GetPartialViewObject();
}
return View(createUser);
}
Then your page header looks like so:
<%# Page Language="C#" Inherits="ViewPage<MyCreateUserView>" %>
and when you render your partial write:
<% Html.RenderPartial("../MyPartialViewObject ", Model.Blah); %>
Instead of solving that with the pattern you describe (which is generally a great pattern), I solve that with calls to RenderAction and have it return a partial view. That way the code is in one place as each call to each view does not have to worry about marshalling all the data you need. If you want to see a short discussion on how to use it, I would check Haack's blog here: http://haacked.com/archive/2009/11/18/aspnetmvc2-render-action.aspx. You can also check out the discussion on this other post here on SO: ASP.NET MVC Master Page Data

Where to apply logic for a sidebar control in ASP.NET MVC

Take the example of wanting to have a "Latest news items" sidebar on every page of your ASP.NET MVC web site. I have a NewsItemController which is fine for pages dedicating their attention to NewsItems. What about having a news sidebar appear on the HomeController for the home page though? Or any other controller for that matter?
My first instinct is to put the logic for selecting top 5 NewsItems in a user control which is then called in the Master Page. That way every page gets a news sidebar without having to contaminate any of the other controllers with NewsItem logic. This then means putting logic in what I understood to be the presentation layer which would normally go in a Controller.
I can think of about half a dozen different ways to approach it but none of them seem 'right' in terms of separation of concerns and other related buzz-words.
I think you should consider putting it in your master page. Your controller can gather data (asynchronously, of course), store it in a nice ViewModel property for your view (or in TempData) and then you can call RenderPartial() in your master page to render the data.
The keeps everything "separate"
http://eduncan911.com/blog/html-renderaction-for-asp-net-mvc-1-0.aspx
This seems to address the question - even using the instance of a sidebar - but using a feature not included with MVC 1 by default.
http://blogs.intesoft.net/post/2009/02/renderaction-versus-renderpartial-aspnet-mvc.aspx
This also indicates the answer lies in RenderAction.
For anyone else interested, here's how I ended up doing it. Note you'll need to the MVC Futures assembly for RenderAction.
Basically you'd have something like this in your controller:
public class PostController
{
//...
public ActionResult SidebarBox()
{
// I use a repository pattern to get records
// Just replace it with whatever you use
return View(repoArticles.GetAllArticles().Take(5).ToList());
}
//...
}
Then create a partial view for SidebarBox with the content you want displayed, and in your Master Page (or wherever you want to display it) you'd use:
<% Html.RenderAction<PostController>(c => c.SidebarBox()); %>
Not so hard after all.
You can create a user control (.ascx) and then call RenderPartial().
Design a method in your controller with JsonResult as return type. Use it along with jQuery.
Use RenderAction() as suggested by elsewhere.
News section with ASP.NET MVC

Asp.net mvc: Posting Back from the View

Is it considered better practice to post back to the same controller that did the rendering and redirecting from original controller if necessary? Or is it just the same if one jumps to different controllers from the view?
I create two overloaded actions in the controller, one to render the input form using an HTTP GET and the other to process the form post using an HTTP POST. Something like this:
public ViewResult Foo()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ViewResult Foo( FormCollection form )
{
// process input
if (inputOK)
return RedirectToAction("Index");
return View();
}
The benefit of doing it this way is that if there's an error, the view gets re-rendered with any error and validation messages. If it's successful, there's a redirect to another action, which avoids the duplicate posting warning on browsers if a user refreshes the page - see Post/Redirect/Get on Wikipedia and this blog entry by Stephen Walther.
There are alternatives to taking a FormCollection, e.g. a list of simple parameters or binding to an object. See this article by ScottGu.
I think that the action that is being called should be contained within a relevant controller for that action. If the view needs to call the action it should call it from the relevant controller, not necessarily the controller that it was spawned from.
If you have an inventory controller you don't want to define actions that relate to administration even if an inventory screen might have an administration action on it, as an example.

Resources