This question is locked. New answers and comments are not allowed.
Hi All,
The Telerik MVC menu component does not work correctly with MVC4, please let me state before we go any further, Iv'e gone through all the related posts I can find in the 'Menus' forum and downloaded the samples provided by Telerik staff and I have been able to reproduce the same issue in all of them.
I do also believe that I have a solution, but this will require Telerik to make changes to the MVC Menu's code and re-release.
Starting at the top
I have an MVC 4 application that serves my local network, this application is called 'Intranet'.
Within this application some users have their own area's.
When using route value dictionaries in the user areas, to create custom menus using the shared functionality in the root of the application, the MVC Menu control ignores the area value, then proceeds to throw an 'Object reference not set to an instance of an object
Within the views of these areas, menus can vary from page to page, depending on the page being viewed.
In the root of the application there is some shared functionality, namely controllers and views to facilitate logging on / off the system.
When using route value dictionaries in the user areas, to create custom menus using the shared functionality in the root of the application, the MVC Menu control ignores the area value, then proceeds to throw an 'Object reference not set to an instance of an object' exception upon accessing the page, due to the fact that in cannot find the controller it wants in the area that it is in.
A similar post in the telerik forum here ( http://www.telerik.com/community/forums/aspnet-mvc/menu/areas-in-mvc2.aspx ) which suggests using an empty area name when referencing controllers in the root of the application, and even following the advice in the above post this does not work.
The Implementation
The application is currently laid out as follows:
Areas
----> Sam
----> Controllers
----> Models
----> Views
----> Home
Controllers
Models
Views
----> Account
----> Home
----> Shared
As you can see the 'Sam' area has it's own controllers, model's & views folder as expected, and we also have the standard controllers, model's & views folders in the root of the app.
in 'Areas->Sam->Views->Home' is the following razor file called 'index.cshtml'
As you can see, I have 2 options on the menu, home which as expected resolves to '/sam/' and correctly displays the above file, the second one however causes the afore mentioned 'Null reference exception' when browsing to the page '/sam/' which looking at the code, and seeing that it is using the correct route value dictionary to refer to the root of the app, should not happen.
If I comment the line out in the menu that creates that link, then everything works fine, so I know that it's the MVC Menu throwing the exception.
Another post in the this forum suggested that this is a common problem with all action link types, and that none of them render correctly with MVC Areas, this is not true as I can create a link to the exact 'Logout' controller I need using the following:
This renders the link absolutely correctly, and as expected, but this option CANNOT be used with the MVC Menu as there is NO override that allows it, I have no choice in the menu but to use 'Action(string, string, string, RouteValueDictionary), also note that the action link way does not attempt to validate if the controller exists, and consequently throw said exception if it does not.
I believe that 2 things are required to fix this:
1) If Telerik where to provide the same functionality and overrides in the construction of the action parameter for the menu components as already exists in the standard action & route link calls that developers are used to, then problems like this could be resolved more easily.
2) Telerik should not prevent the view from rendering by throwing the exception seen, in my honest opinion it's far better to mirror the same behaviour that is seen in existing razor code, and simply not draw a given menu item if the controller does not exist. There are methods in the MVC Helpers that will behave in this fashion if asked to render things like links that don't exist, as way of an example the standard 'Html.ActionLink' call will still attempt to render a link if an action does not exist, granted, it will go no where and cause a 404 when clicked, but to most developers this is better than throwing a 'Null Reference' and leaving them scratching their head with an entire view that does not render at all.
The Telerik MVC menu component does not work correctly with MVC4, please let me state before we go any further, Iv'e gone through all the related posts I can find in the 'Menus' forum and downloaded the samples provided by Telerik staff and I have been able to reproduce the same issue in all of them.
I do also believe that I have a solution, but this will require Telerik to make changes to the MVC Menu's code and re-release.
Starting at the top
I have an MVC 4 application that serves my local network, this application is called 'Intranet'.
Within this application some users have their own area's.
When using route value dictionaries in the user areas, to create custom menus using the shared functionality in the root of the application, the MVC Menu control ignores the area value, then proceeds to throw an 'Object reference not set to an instance of an object
Within the views of these areas, menus can vary from page to page, depending on the page being viewed.
In the root of the application there is some shared functionality, namely controllers and views to facilitate logging on / off the system.
When using route value dictionaries in the user areas, to create custom menus using the shared functionality in the root of the application, the MVC Menu control ignores the area value, then proceeds to throw an 'Object reference not set to an instance of an object' exception upon accessing the page, due to the fact that in cannot find the controller it wants in the area that it is in.
A similar post in the telerik forum here ( http://www.telerik.com/community/forums/aspnet-mvc/menu/areas-in-mvc2.aspx ) which suggests using an empty area name when referencing controllers in the root of the application, and even following the advice in the above post this does not work.
The Implementation
The application is currently laid out as follows:
Areas
----> Sam
----> Controllers
----> Models
----> Views
----> Home
Controllers
Models
Views
----> Account
----> Home
----> Shared
As you can see the 'Sam' area has it's own controllers, model's & views folder as expected, and we also have the standard controllers, model's & views folders in the root of the app.
in 'Areas->Sam->Views->Home' is the following razor file called 'index.cshtml'
@using Telerik.Web.Mvc.UI
@{
ViewBag.Title = "Intranet | Sams Portal";
}
<h2>Sams Portal</h2>
<p>Hello Sam this is where all your tools will appear</p>
@section menu
{
@(Html.Telerik().Menu()
.Name("menu")
.Items(menu =>
{
menu.Add().Text("Home").Action("Index", "Home");
menu.Add().Text("Logout").Action("Logout", "Account", new { area = "" });
}))
}
As you can see, I have 2 options on the menu, home which as expected resolves to '/sam/' and correctly displays the above file, the second one however causes the afore mentioned 'Null reference exception' when browsing to the page '/sam/' which looking at the code, and seeing that it is using the correct route value dictionary to refer to the root of the app, should not happen.
If I comment the line out in the menu that creates that link, then everything works fine, so I know that it's the MVC Menu throwing the exception.
Another post in the this forum suggested that this is a common problem with all action link types, and that none of them render correctly with MVC Areas, this is not true as I can create a link to the exact 'Logout' controller I need using the following:
@Html.ActionLink("Logout","Logout", new { area = "", controller = "Account"})This renders the link absolutely correctly, and as expected, but this option CANNOT be used with the MVC Menu as there is NO override that allows it, I have no choice in the menu but to use 'Action(string, string, string, RouteValueDictionary), also note that the action link way does not attempt to validate if the controller exists, and consequently throw said exception if it does not.
I believe that 2 things are required to fix this:
1) If Telerik where to provide the same functionality and overrides in the construction of the action parameter for the menu components as already exists in the standard action & route link calls that developers are used to, then problems like this could be resolved more easily.
2) Telerik should not prevent the view from rendering by throwing the exception seen, in my honest opinion it's far better to mirror the same behaviour that is seen in existing razor code, and simply not draw a given menu item if the controller does not exist. There are methods in the MVC Helpers that will behave in this fashion if asked to render things like links that don't exist, as way of an example the standard 'Html.ActionLink' call will still attempt to render a link if an action does not exist, granted, it will go no where and cause a 404 when clicked, but to most developers this is better than throwing a 'Null Reference' and leaving them scratching their head with an entire view that does not render at all.