Mvc Widgets disappear in detailed view

28 May 2016

Usually people will write different mvc widgets for each unique pages in their site, so they will not encounter this scenario.

When things become little bit complex, like you are going to write two controller actions in the same widget. This issue kicks in.

Example:

Consider that you are designing a registration page, where user can either use direct registration or registration through Social platforms. So its logical to create two controller actions in the same custom MVC widget. So the related actions are performed from a single controller.

Consider that you have another custom MVC widget dropped on the same page, that can accept the HTML content from  the user.

namespace SitefinityWebApp.Mvc.Controllers
{
    [ControllerToolboxItem(Name = "CustomMessage", Title = "CustomMessage", SectionName = "MvcWidgets")]
    [Telerik.Sitefinity.Web.UI.ControlDesign.ControlDesigner(typeof(CustomMessageDesigner))]
    public class CustomMessageController : Controller
    {
        /// 
        /// Gets or sets the message.
        /// 
        public string HTMLMessage{ get; set; }

        /// 
        /// This is the default Action.
        /// 
        public ActionResult Index()
        {
           
            var model = new CustomMessageModel()
            {
                 HTMLMessage = this.HTMLMessage
            };
           
            return View("Default", model);
        }
    }
}

When you are on URL http://domain.com/registration. Both mvc controls displays properly as expected.

but when you select the option to register through social platforms, then above URL with the particular social action will be as follows

http://domain.com/registration/social

The registration widget has an action defined in its controller. But think about this CustomMessage Controller. It doesn't have any matching action. So this would result in UnKnowAction error. There by the widget disappears in /registration/social path.

There are two solutions for this issue

1) Simple one for simple CustomMessage widget

IF your CustomMessage widget will never have a second action defined on it. Then you can simple add the following handler to the CustomMessageController, to map all the UnKnownActions to an Index() action on the controller.

protected override void HandleUnknownAction(string actionName) {  
          Index().ExecuteResult(ControllerContext); 
}

Above will work flawlessly. when any action doesn't match with action defined in its controller it simply handles the exception by showing the default Index() Controller.

2) If your CustomMessage controller will feature more than one action

Then you have to explicitly change open advanced properties of each MVC widget, and use same UrlkeyPrefix to each content widget on this page that will render on social view.

Example:

To render in the controller, create a new action and put ActionName attribute to this method specifying the action name. in our case "social" is the new action.

namespace SitefinityWebApp.Mvc.Controllers
{
    [ControllerToolboxItem(Name = "CustomMessage", Title = "CustomMessage", SectionName = "MvcWidgets")]
    [Telerik.Sitefinity.Web.UI.ControlDesign.ControlDesigner(typeof(CustomMessageDesigner))]
    public class CustomMessageController : Controller
    {
        /// 
        /// Gets or sets the message.
        /// 
        public string HTMLMessage{ get; set; }

        /// 
        /// This is the default Action.
        /// 
        public ActionResult Index()
        {
           
            var model = new CustomMessageModel()
            {
                 HTMLMessage = this.HTMLMessage
            };
           
            return View("Default", model);
        }

        [ActionName("!social")]
        public ActionResult Action2()
        {
           
            var model = new CustomMessageModel()
            {
                 HTMLMessage = this.HTMLMessage
            };
           
            return View("Default", model);
        }
    }
}

So the controls can identify that they have to show a particular action on defined UrlPrefix + ActionName. You can see more detailed over here.

Hope this helps.