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.
Related
I have a view and a partial view. Within the controller action methods, I have a using statement which establishes some back-end threading context, including providing access to a model object for display in the view.
The problem that I'm having is that while the context and the associated model object are available for the main view, they are disposed before the partial view is rendered. This seems to be the case regardless of whether I pass the model object from the view to the partial view, or reference it some other way.
The controller view action method:
public ActionResult Index()
{
using (var context = GetContext()) {
return View(Context.MyModelObject);
}
}
The controller partial view action method:
[ChildActionOnly]
public ActionResult MyPartialView(ModelObject modelObject)
{
return PartialView(modelObject);
}
The view:
#model ModelObject
#Model.Name
#{Html.RenderAction("MyPartialView", "MyController", new {modelObject = #Model});}
The partial view:
#model ModelObject
#foreach(var item in Model.Items) {
<div>#item.Name</div>
}
If I comment out the RenderAction line of the view, the view displays just fine, accessing the property of the model because the context has not yet been disposed at the end of the using.
However, if I leave it in with the intent of the partial view being rendered, the context has been disposed of, leaving my model object no longer accessible. I would think the using in the main view controller method would not be finished until the view and all its partial views are rendered, but that doesn't seem to be the case. Are partial views deferred to be rendered at some other time? Is there a way around this?
Right now I have a solution which will involve writing a lot of extra code: making a "view model" object which has only the bits of the model object that I need for display in this specific view while it hasn't yet been disposed, then having the view and partial views use that. However, this will be very undesirable as it will result in a lot of duplication between the model and the view models, which will be a subset. It would be very convenient to use the model directly in the view.
The other possibility is that we could alter our backend to dispose of things differently such that they are still available for the partial view whenever it gets around to rendering, but this also seems like a hack.
In summary, is there a better way to do this in the view/controller? Am I making some erroneous assumptions?
MVC was designed with Unit testability in mind. As such, it doesn't render the view when you call View(), it just creates a structure which gets rendered after it returns from the controller.
This design makes it easier to unit test controllers because it doesn't actually require an active web server connection to execute the controller logic.
But, this also means that since you have a using statement in your controller, the view is not actually rendered until after you have returned from the function, and thus the using has called delete on the data context. Thus, your queries will not execute.
You get around this by executing the query within the controller, such as calling .ToList() on the object. You still have to be careful not to execute any lazy operations after returning.
However, a better approach is to not pass your data objects directly to the view, but instead use a view model which you populate from the returned data objects.
Try this
#Html.Partial("MyPartialView", Model)
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.
I am moving the views of an old project from ASPX to Razor, I have almost finished with it without any major issues, but I have come to this kind of problem with some strongly typed views. The thing is that when the controller returns the view using
return View(model)
the View Egine finds the proper views, always and for all the controller actions, but the model is always null when the View try to access it. But if I use
return View (ViewName, model)
Everything works like a charm.
So my question is why is the first option working perfectly when the views are using ASPX and not with Razor?
and
Why is it finding the view but passing a null model?
I am developing an MVC solution and I want to have a plugin option for some partial views I am creating. I have separate assembly for each plugin that contains the PartialView as an embedded resource and the viewmodel class that it references. I use a virtualfile provider to find the required PartialView and this works great...until I try to use the ViewModel for the partial.
To render the partial view, I have two properties in the Model that get set at runtime depending on the option chosen...so I use the following:
Html.RenderPartial(Model.PartialViewName, Model.PartialViewModel)
where Model.PartialViewModel is an interface that all the view models in the separate assemblies implement.
I get the following error when the partial view is rendering: error CS1061 'object' does not contain a definition for '{PropertyName}' and no extension method '{PropertyName}' accepting a first argument of type 'object' could be found..." This error occurs for whatever property on the partial viewmodel I'm trying to access.
However, when in debug mode, I can see the viewmodel that has been passed to the partial view and it is correct and all the properties are there and populated. I have even went so far as to remove the plugin-ness and just reference the named classes and types (instead of interfaces) and I still get this error.
Any ideas? Anyone been able to put a partial view and its viewmodel in a separate assembly and get it to work? Thank you.
I have created a partial view in my asp.net mvc solution that will show a list of items from a database. However I get an error saying: Object reference not set to an instance of an object.
I'm not sure why this is happening because as far as I'm concerned everything is fine. The list of items are venues which is controlled via VenuesController BUT the partial view is inside the /shared/ folder and NOT the /venues/ folder for the views so is asp.net complaining because it's not linking the two together?
This is the code I have in my VenuesController:
//
// GET: /Venues/
public ActionResult Index()
{
return View(_repository.ListAll());
}
public ActionResult VenuesList()
{
return PartialView("VenuesList",_repository.ListAll());
}
The Index() works fine and displays the data in /Views/Venues/Index.aspx but the VenuesList() throws the error :/
Thanks.
The error message that you mention:
Object reference not set to an instance of an object.
typically deals when a property of a collection is referenced and it is null. You might want to make sure that the list of items is either:
Not empty.
Instantiated properly.
Any code from the Controller-side of things might make this a bit easier to figure out.
Update:
I'm not completely sure what the Venue model looks like, however two things could be occurring here.
In the constructor for Venue (which should be passed the list from your repository),
the List property inside of Venue is never being instantiated prior to Adding the
items in.
or
The repository is not returning any values.
Additional code displaying the Venue class and it's constructor might be helpful.
Make sure that any properties in your model that you reference in your partial view are not null. I've had similar cases where the model passed into the partial view has some null fields that, when rendered, throw NullReferenceExceptions.
E.g. something like
<%: Model.Property %>
or, especially:
<%: Model.Property.ChildProperty %>
i.e. if "Property" is null, then trying to access "ChildProperty" WILL throw a NulLReference exception.