Problems returning PartialViews from controller - asp.net-mvc

I am using MVC 4 and I have some areas in my project and some Views and Partial Views within each area:
Areas
AdminArea => one area and so on
Views
Customer
Customer.cshtml => my View
_CustomerDetails.cshtml => my partial View
In my controller, CustomerController I have the following code that fails:
return PartialView("_CustomerDetails", model) => fails to find my partial view.
However, if I call
return PartialView("~/Areas/AdminArea/Views/Customer/_CustomerDetails.cshtml", model)
the code executes successfully.
My Views (not partial views) all work ok. I even have some some partial views (also in the same area) that render ok without specifying the full path, but for some reason, for the most of them the above code fails in constructor saying that:
The partial view '_CustomerDetails' was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Customer/_CustomerDetails.cshtml a.s.o. ... => and is searching in global not in Admin area.
Is there any way to fix this problem without having to specify the full path to my PartialViews in code? (like passing area="Admin" like I do in the .cshtml file).
I am not using any custom ViewEngine and I have called AreaRegistration.RegisterAllAreas() in Global.asax.cs.
Thanks,
Tamash

I am really sorry for even posting this question:
The call from the controller worked fine, but the problem was that I was calling from javascript to get the PartialView through an action and I didn't specify the full name for that action. That's why the partial view wasn't returned since the method responsible for returning it wasn't being called at all.
Sorry about that: the code is a bit complex and I got lost in details around Ajax calls.

seems weird, try adding a view from controller action method i.e right click action method in controller, add view, make a view a partial view and see where it adds it.. check if it is the same location as you are putting, if not there is some structure prob/bug.

Related

Adding a View without a model MVC 5

I need to create a simple view with 3 links on it ( Administration type page ), I tried adding a View called index to a Directory called Administration but when I try to navigate to it it throws a resource not found error. I am brand new to MVC coming from Web Forms so sorry if this is a stupid question ;)
Firts Add a controller which will come with Index method. Right click on Index Method and select Add View.
Add all Html you want to add in that view and your page is ready without adding a Model.
You need to have a controller to render the view.
For instance, if you had an AdminController with a method similar to something like public ActionResult Index() { return View(); } this would render the index view where you could place your html/links etc.
The view itself doesn't need a model this way as you are not supplying anything when returning the View().
You could then navigate to the page by http://xxx/Admin/Index or, 'http://xxx/Admin/'.
It is well worth looking around SO and other various websites for MVC queries!
Good luck.

Failed to return partial view from area

Basically I've just created an Area in my ASP.NET MVC4 application.
It all works great etc, however when I want to return a PartialView as shown below:
return PartialView("_ImportSessionsTable", viewModel);
(not that the above call is called from the area(admin) view)
I get the following error:
The partial view '_ImportSessionsTable' was not found or no view
engine supports the searched locations. The following locations were
searched: ~/Views/ImportSessions/_ImportSessionsTable.aspx
~/Views/ImportSessions/_ImportSessionsTable.ascx
~/Views/Shared/_ImportSessionsTable.aspx
~/Views/Shared/_ImportSessionsTable.ascx
~/Views/ImportSessions/_ImportSessionsTable.cshtml
~/Views/ImportSessions/_ImportSessionsTable.vbhtml
~/Views/Shared/_ImportSessionsTable.cshtml
~/Views/Shared/_ImportSessionsTable.vbhtml
The thing is: as far as I can see it isn't looking for the view in the area folder (admin) which is where I have the view stored. How can I get it to look there? Whenever I call return View(); it works fine so it's only when I specify the view as a string.
How can I get it to look there?
You could specify the full location of the partial to be rendered:
return PartialView("~/Areas/Admin/Views/ImportSessions/_ImportSessionsTable.cshtml", viewModel);
You could also consider overriding where the viewengine searches for views, but that might be a little extreme for what you're looking for. See here: Link

"Cannot Resolve Partial View X" in Umbraco 6 Html.Partial

I'm using Umbraco 6, and am using the new MVC architecture. I have a document type view template, which has a view model, which is instantiated and has it's properties populated from the controller. One of these properties is a collection, and in the view template I iterate through the collection and render out a Partial View with a separate view model, using 'Html.Partial("partialName", modelObject)'
The weird problem I'm having is that firstly, in Visual Studio I get a ReSharper warning telling me that it cannot resolve a partial view with that name (I have checked 50 times and I've spelt it correctly). Additionally when I then navigate to the page, I get the trusty ol' "Object reference not set to an instance of an object" YSOD.
I have debugged the code, and the controller action is hit fine, the logic to instantiate the view model for the document type template works fine, and populates the properties correctly, I've also made sure the properties are still set inside the view and the loop for rendering out the collection items correctly instantiates a view model object per collection item and sets the properties correctly. It breaks when it hits the Html.Partial.
Document Type View Code below:
#foreach (KeyValuePair<decimal, IPublishedContent> result in Model.Results)
{
PropertySearchResultViewModel model = ObjectMapper.SearchResultToViewModel(result);
Html.RenderPartial("PropertySearchResultDesktop", model);
}
Partial View Code below:
#using Production.Umbraco.Extensions.Models.ViewModels;
#inherits UmbracoViewPage<PropertySearchResultViewModel>
<article id="property-result-#Model.Node.Id.ToLower()">
<p>#Model.Node.Name</article>
<p>Distance: #Model.Distance Miles</p>
</article>
Here is a screenshot of my VS Solution tree:
The 'NewHomes.cshtml' document type view template is returned from the NewHomesController and the view is calling the 'PropertySearchResultDesktop.cshtml' partial view, which was created from the Umbraco back office, and was placed their automatically.
The Umbraco website says that you can and should place your partial views here
http://our.umbraco.org/Documentation/Reference/Mvc/partial-views
But no matter what I try to do, it just wont render the partial. I've seen one other question about this on SO but the answer was just to place it in MacroPartials instead, which I dont want to do as part of the benefit of using Partial Views in Umbraco 6 is that they inherit from UmbracoViewPage with a strongly typed model declaration, which MacroPartials don't.
Has anyone encountered this before?
Fixed. The issue was with the model I was passing to the document type view from the controller.
In the Umbraco documentation it says, you can create a controller to hijack the Umbraco route and serve up your own view with a custom model, like so:
public ActionResult Index(RenderModel model)
{
SearchResultsViewModel viewModel = new SearchResultsViewModel
return CurrentTemplate(viewModel);
}
and in my view I had:
#inherits UmbracoViewPage<SearchResultsViewModel>
However, it seems as though, in order to do that, you must make sure your custom view model in inherits from RenderModel with a constructor that takes RenderModel as a parameter and then sets some properties on the base object, like so:
public class SearchResultsViewModel :RenderModel
{
public SearchResultsViewModel(RenderModel model) : base(model.Content, model.CurrentCulture)
{
}
}
Previously, my view model had not inherited from anything and had a parameterless constructor.
This article led me to the right answer.
http://www.ben-morris.com/using-umbraco-6-to-create-an-asp-net-mvc-4-web-applicatio
Also, as a side note, I still get the ReSharper warning of "Cannot resolve partial view PropertySearchResultDesktop" but I think that's a ReSharper bug rather than an error.
Even with a full path and file extension in the call, it still complains.
I do find it odd though that while debugging, even with my old controller code, no exception was thrown at the model binding stage or inside the controller, or in the view until it go to the Html.Partial call.
Anyway, I hope this helps anyone having the same issue.

Encapsulating User Controls in ASP.NET MVC

Sorry if this is a basic question - I'm having some trouble making the mental transition to ASP.NET MVC from the page framework.
In the page framework, I often use ASCX files to create small, encapsulated chunks of functionality which get inclded in various places throughout a site. If I'm building a page and I need one of these controls - I just add a reference and everything just works.
As far as I can tell, in MVC, the ASCX file is just a partial view. Does this mean that wherever I want to add one of these units of functionality I also have to add some code to the controller's action method to make sure the relevant ViewData is available to the ASCX?
If this is the case, it seems like a bit of a step backwards to me. It means, for example, that I couldn't just 'drop' a control into a master page without having to add code to every controller whose views use that master page!
I suspect I'm missing something - any help would be appreciated.
Thanks,
- Chris
As far as I can tell, in MVC, the ASCX
file is just a partial view. Does this
mean that wherever I want to add one
of these units of functionality I also
have to add some code to the
controller's action method to make
sure the relevant ViewData is
available to the ASCX?
Yes.
However, you can use a RenderAction method in your view instead of RenderPartial, and all of your functionality (including the data being passed to the sub-view) will be encapsulated.
In other words, this will create a little package that incorporates a controller method, view data, and a partial view, which can be called with one line of code from within your main view.
Your question has been answered already, but just for sake of completeness, there's another option you might find attractive sometimes.
Have you seen how "controls" are masked on ASP.NET MVC? They are methods of the "HtmlHelper". If you want a textbox bound to "FirstName", for example, you can do:
<%= Html.Textbox("FirstName") %>
And you have things like that for many standard controls.
What you can do is create your own methods like that. To create your own method, you have to create an extension method on the HtmlHelper class, like this:
public static class HtmlHelperExtensions
{
public static string Bold(this HtmlHelper html, string text)
{
return "<b>" + text + "</b>\n";
}
}
Then in your view, after opening the namespace containing this class definition, you can use it like this:
<%= Html.Bold("This text will be in bold-face!") %>
Well, this is not particularly useful. But you can do very interesting things. One I use quite often is a method that takes an enumeration and created a Drop Down List with the values from this enumeration (ex: enum Gender { Male, Female }, and in the view something like Gender: <%= Html.EnumDropDown(Model.Gender) %>).
Good luck!
You can render a partial view and pass a model object to.
<% Html.RenderPartial("MyPartial", ViewData["SomeObject"]);
In your partial view (.ascx) file, you can then use the "Model" object (assuming you've inherited the proper object in your # Control deceleration) to do whatever you need to with that object.
You can, ofcourse, not pass and Model and just take the partial view's text and place it where you want it.
In your main view (.aspx file), you will need to define the proper object in the ViewData that you're passing to the partial view.
Another method you can do is use:
<% Html.RenderAction("MyAction", "MyController", new { Parameter1="Value1"}) %>
What the previous method does is call a controller Action, take its response, and place it where you called the "RenderAction()" method. Its the equivalent of running a request against a controller action and reading the response, except you place the response in another file.
Google "renderaction and renderpartial" for some more information.

Populating the model for a shared view, embedding a shared view within another view

I'm trying to embed a small view snippet that steps through a model fragment that works fine when I embed it in a single controller and pass it to a view like so;
Controller:
return View(_entities.formTemplate.ToList());
View:
http://www.pastie.org/666366
The thing is that I want to be able to embed this particular select box in more than just this single action / view, from the googling I've been doing this appears that it should go into a shared view, but I'm not clear then on how I could populate the model within that view from the controller? (or maybe I'm completely missing the purpose for shared views?)
In the other MVC framework I'm accustomed to working with there is the concept of a filter where you can call code before or after any action and mod the model as it passes the controller and goes to the view, is such a thing possible in .net mvc?
Any assistance appreciated.
You'll want to use the HtmlHelper method DropDownList() in order to create a input:
<%= Html.DropDownList("id", new SelectList(formBuilder, "ID", "Name")) %>
You probably want to use a ViewUserControl here.
You have a couple of options if you go that route. If it's model data that is easily available, recreate it at the call site of your RenderPartial like so:
<%=Html.RenderPartial("ViewName", new ModelData())%>
If it's data that is dependent on the current model data, then you'll need to pass that data somehow to your partial view.
ASP.Net MVC also has the concept of before/after controller actions. You decorate your controller method with an Attribute that derives from ActionFilterAttribute. In there, you have access to OnActionExecuting and OnActionExecuted.

Resources