Having multiple mvc widgets in one page
Hi. I have several pages that needs to have 2 mvc widgets. When one of the page gets reference with a subpage, the mvc controller calls the action method name that matches the subpage. (for example: with url path - "home/default", controller "home" will call action method "default". The problem is with having another widget that is shared across pages since the other widget needs to have all the action method that the per page widget has in order to be accessed in all subpages. Can I assign the default controller action method ("Index") to be called always regardless of the subpage? What would be the best way to handle a single action method that will be called always regardless of the subpage? Is it also possible to create dynamic action method by over writing the controller factory?
Hi Andrew,
Unfortunately, this cannot be done so simple, because by design every MVC control tries to resolve the url of the page where it stands. Because of this when you do not have an action with the name of the your page specific control, the shared one does not render at all.
However, there is something you can do for your Shared control. You can change its type from type="Telerik.Sitefinity.Mvc.Proxy.MvcControllerProxy" to a custom one - type="SitefinityWebApp.MvcExtended.CustomMvcControllerProxy", that inherits MvcProxyBase.
In the toolbox config you can change the type of the control like this:
<
add
enabled
=
"True"
title
=
"MvcWidgets"
name
=
"MvcWidgets"
>
<
tools
>
<
add
enabled
=
"True"
type
=
"SitefinityWebApp.MvcExtended.CustomMvcControllerProxy"
controllerType
=
"SitefinityWebApp.Mvc.Controllers.MySharedWidgetController"
title
=
"MySharedWidget"
ControllerName
=
"SitefinityWebApp.Mvc.Controllers.MySharedWidgetController"
visibilityMode
=
"None"
name
=
"MySharedWidget"
/>
</
tools
>
</
add
>
In the OnPreRender method of the MvcControllerProxy, ExecuteController is called which gets the action that needs to be executed and executes it like this:
string
actionName =
this
.Controller.RouteData.GetRequiredString(
"action"
);
this
.Controller.ActionInvoker.InvokeAction(
this
.Controller.ControllerContext, actionName)
I have this exact problem but your solution does not work for me.
I then made my own class that pretty much is just your CustomMvcControllerProxy so I could set breakpoints but there were 2 issues:
1. I can't resolve SitefinityActionInvoker. It looks like it's in the Telerik.Sitefinity.Mvc namespace but I can't see it there
2. I just commented it out so I could at least step through and see how the method is working, but after assigning that class to my Mvc control, the breakpoints do not get hit at all.
This really is a major problem that I MUST solve for the project I'm working on. All of my widgets are built with MVC and to think that because some pages needs a url name in the last segment will break the rest of the widgets on the page.....it's very concerning. If this solution of yours worked I figured I could just make different proxies for different widgets and handle the default actions, but I can't even get your initial one to work. Please help
I've got it using my proxy controllers, can you please tell me where I can reference SitefinityActionInvoker or give me the class itself so I can use it?
Please.....anyone? I just need to resolve that one class so I can test this
Hi Ryan,
If you are using Sitefinity 6.3 and above, you will not be able to resolve SitefinityActionInvoker. What I can suggest is to override the HandleUnknownAction() method in your controller as shown below:
public
class
MyMVCWidgetController : Controller
....
protected
override
void
HandleUnknownAction(
string
actionName)
this
.ActionInvoker.InvokeAction(
this
.ControllerContext,
"Index"
);
return
;
Thank you very much. That did the trick.
I suppose I could have just implemented that myself but I was under the impression you needed to run it through the custom Sitefinity Invoker. Glad to see it's just using the built in MVC handling and one less dependency.
Thanks again
Something else that I noticed for anyone that may have this issue, and it regards using this in a regular MVC application as well:
I usually use my actions with return View(model) and let MVC choose my view from my views folder, but using this, you need to specify the view name ie. return View("Index", model) or else the action will try to look for the view using the previous incorrect route as the view name