U4-4604 - Surface Controller functionality changed in 7.1 breaking site

Created by Damian Green 03 Apr 2014, 23:00:21 Updated by Shannon Deminick 14 Apr 2014, 09:01:51

Relates to: U4-4682

Please view this ticket on or to see some background.

http://our.umbraco.org/forum/umbraco-7/using-umbraco-7/49676-Partial-Views-No-engine-supports-the-searched-locations?p=0#comment177524

Basically I have a surface controller

[ChildActionOnly] public ActionResult Index() { ContactVM model = new ContactVM();

        return PartialView("ContactForm", model);
    }

A Template page that calls the Surface GET

@Html.Action("Index", "ContactUsSurface")

And a partial that displays the view and model.

The site was upgraded fro 7.0.2 to 7.1 and it has stopped working.

It appears the surface controller is no longer including the Partials folder in its locations. If i add the Partial to the Shared folder it finds it but then i get a message saying

The model item passed into the dictionary is of type 'Umbraco.Web.Models.RenderModel', but this dictionary requires a model item of type 'mytype'

which appears that the Controller doesnt think its a Surface Controller but a Render Controller used in Route Hijacking (i think - as ive not used them before but read about them).

If i create a folder called ControllerNameSurface (so without the Controller suffix) it works.

Apparently this is a bug but i have to be honest and think this is a far better way to organise the files that belong to surface controllers. Its is much closer to actual MVC sites and easier to find stuff. Please let it stay or be an option to have it like this! :)

1 Attachments

Download damiancode.zip

Comments

Damian Green 04 Apr 2014, 00:05:01

On the one that works - it doesnt like the POST and gets the model error again.

The model item passed into the dictionary is of type 'Umbraco.Web.Models.RenderModel', but this dictionary requires a model item of type 'proj.Web.Models.ContactVM'.


Stephan 04 Apr 2014, 10:07:57

Can you tell what's the type of the view, ie what's its inherits/model directive?


Sebastiaan Janssen 07 Apr 2014, 11:12:20

@Damian.Green I've fixed the routing issue for 7.1.1 (out very soon). Please add example code for your POST error though, so I can investigate that too.


Damian Green 07 Apr 2014, 12:16:48

sorry for the delay... missed the update.

The Html.Action is on an UmbracoTemplatePage and my View just has a model of: @model Project.Web.Models.ContactVM

If i change to UmbracoViewPage<Project.Web.Models.ContactVM> i still get the same error.

My form is as follows:

@using (Html.BeginUmbracoForm<Project.Web.Controllers.ContactUsSurfaceController>("SubmitContactForm", null, new { id = "contact-form", @class = "contact-form" }))

and my action:

[HttpPost] public ActionResult SubmitContactForm(ContactVM model) { if (!ModelState.IsValid) return CurrentUmbracoPage();

...code ommitted }

Does that help any?

Let me know if you need anything specific.

Damian


Damian Green 07 Apr 2014, 13:08:17

Still getting an error on POST.

The model item passed into the dictionary is of type 'Umbraco.Web.Models.RenderModel', but this dictionary requires a model item of type 'Project.Web.Models.ContactVM'.

here is the stack trace: [InvalidOperationException: The model item passed into the dictionary is of type 'Umbraco.Web.Models.RenderModel', but this dictionary requires a model item of type 'Project.Web.Models.ContactVM'.] System.Web.Mvc.ViewDataDictionary1.SetModel(Object value) +175 System.Web.Mvc.ViewDataDictionary..ctor(ViewDataDictionary dictionary) +361 System.Web.Mvc.WebViewPage1.SetViewData(ViewDataDictionary viewData) +49 Umbraco.Web.Mvc.UmbracoViewPage1.SetViewData(ViewDataDictionary viewData) +729 System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance) +98 System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) +107 Umbraco.Core.Profiling.ProfilingView.Render(ViewContext viewContext, TextWriter writer) +93 System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +291 System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +13 System.Web.Mvc.<>c__DisplayClass1a.<InvokeActionResultWithFilters>b__17() +23 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func1 continuation) +245 System.Web.Mvc.<>c__DisplayClass1c.b__19() +22 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func1 continuation) +245 System.Web.Mvc.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19() +22 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList1 filters, ActionResult actionResult) +176 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +311 System.Web.Mvc.Controller.ExecuteCore() +103 System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +86 System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +10 Umbraco.Web.Mvc.UmbracoPageResult.ExecuteControllerAction(ControllerContext context, IController controller) +78 Umbraco.Web.Mvc.UmbracoPageResult.ExecuteResult(ControllerContext context) +290 System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +13 System.Web.Mvc.<>c__DisplayClass1a.b__17() +23 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func1 continuation) +245 System.Web.Mvc.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19() +22 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func1 continuation) +245 System.Web.Mvc.<>c__DisplayClass1c.b__19() +22 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func1 continuation) +245 System.Web.Mvc.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19() +22 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func1 continuation) +245 System.Web.Mvc.<>c__DisplayClass1c.b__19() +22 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList1 filters, ActionResult actionResult) +176 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +311 System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__19() +23 System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +19 System.Web.Mvc.Async.<>c__DisplayClass81.b__7(IAsyncResult _) +10 System.Web.Mvc.Async.WrappedAsyncResult1.End() +55 System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +39 System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +23 System.Web.Mvc.Async.WrappedAsyncResult1.End() +55 System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +29 System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10 System.Web.Mvc.<>c__DisplayClass8.b__3(IAsyncResult asyncResult) +25 System.Web.Mvc.Async.<>c__DisplayClass4.b__3(IAsyncResult ar) +23 System.Web.Mvc.Async.WrappedAsyncResult`1.End() +55 System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +31 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9688704 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155


Sebastiaan Janssen 07 Apr 2014, 13:54:01

Only now I noticed that you're changing the view's model to UmbracoViewPage. I'm not sure what you're trying to do there, but this could never have worked. The error is 100% correct: you're sending a ContactVM class to a view that expects a UmbracoViewPage. I think you're confusing route hijacking with SurfaceControllers.


Damian Green 07 Apr 2014, 13:55:24

If i put the view back in the partials folder i get the file not found in locations. If i move the file to the shared folder I'm back with the render model error.

The model item passed into the dictionary is of type 'Umbraco.Web.Models.RenderModel', but this dictionary requires a model item of type 'proj.Web.Models.ContactVM'.

Doesn't seem any different to 7.1.


Sebastiaan Janssen 07 Apr 2014, 13:57:00

@Damian.Green Let's concentrate on the partials folder. Is this still a problem in the nightly that I sent you?


Damian Green 07 Apr 2014, 14:01:19

it was originally done with @model ContactVM but same error - i just added view page as a test. I am not trying to do route hijacking - just a surface controller for a contact form.

Was working fine in 7.0.2


Sebastiaan Janssen 07 Apr 2014, 14:03:39

@Damian.Green Any chance you can send me the solution as I think we're getting our wires crossed here... :-)


Damian Green 07 Apr 2014, 14:24:11

@sebastiaan view in partials: The partial view 'ContactForm' was not found or no view engine supports the searched locations. The following locations were searched: ~/Views/ContactUsSurface/ContactForm.aspx ~/Views/ContactUsSurface/ContactForm.ascx ~/Views/Shared/ContactForm.aspx ~/Views/Shared/ContactForm.ascx ~/Views/ContactUsSurface/ContactForm.cshtml ~/Views/ContactUsSurface/ContactForm.vbhtml ~/Views/Shared/ContactForm.cshtml ~/Views/Shared/ContactForm.vbhtml

View in shared with @model Project.Web.Models.ContactVM:

The model item passed into the dictionary is of type 'Umbraco.Web.Models.RenderModel', but this dictionary requires a model item of type 'Project.Web.Models.ContactVM'.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: The model item passed into the dictionary is of type 'Umbraco.Web.Models.RenderModel', but this dictionary requires a model item of type 'Project.Web.Models.ContactVM'.

In respect to sending the solution - its pretty big with images etc.. how about i send you the views and controller and model etc? where can i send it to?


Damian Green 07 Apr 2014, 16:13:36

Did you get the files ok?


Sebastiaan Janssen 07 Apr 2014, 17:11:45

@Damian.Green I did thanks! Will look into it more tomorrow, ran out of time today. :)


Sebastiaan Janssen 08 Apr 2014, 11:09:27

@Damian.Green You're sending a ContactVM class into your Thankyou view, return View("Thankyou", model); which is causing your error. :-)


Sebastiaan Janssen 08 Apr 2014, 11:10:13

And with your code in the upcoming 7.1.1 the partial view now gets rendered fine again when it's in the Partials folder.


Damian Green 08 Apr 2014, 12:09:27

okidoke i will give it a blast as soon as available. Thanks.


Sebastiaan Janssen 08 Apr 2014, 12:15:27

@Damian.Green Coolio, just released it, thanks for all the feedback! http://umbra.co/1svNHKb


Damian Green 09 Apr 2014, 22:13:10

All seems ok now Sebastiaan. Out of interest what is the best way to redirect with Umbraco and pass a model like i want to do with the Thankyou page? Only way i can see is by returnng a redirect and passing an id in the query string and reloading the model.

Is there a better way? Normal MVC i would just return the view and model as i was trying to do in the files i sent.


Priority: Normal

Type: Bug

State: Fixed

Assignee:

Difficulty: Normal

Category:

Backwards Compatible: True

Fix Submitted:

Affected versions: 7.1.0

Due in version: 7.1.1

Sprint:

Story Points:

Cycle: