EnterpriseXL
EnterpriseXL

Reputation: 477

Evaluate value from web.config file via ViewBag

The task is simple. I have value in web.config, like this:

 <add key="MenuTypes" value="1,2,3"/>

and in Razor file I need to render some menus based on those value. So If I have value 3 in the config file (MenuTypes), I want to render the item. And If I don't have it, I do not want to render it:

<div>  
            <ul id="setThemUp" class="vehicles">  
                <li><a class="bikes" href="#1">Bikes</a></li>  
                <li><a class="cars" href="#2">Cars</a></li>
                @if (ViewBag.MenuTypes(((int)3).ToString()) > -1)
                {
                   <li><a class="Trucks" href="#3">Trucks</a></li>
               }

            </ul>

I have also tried:

 <div>  
            <ul id="setThemUp" class="vehicles">  
                <li><a class="bikes" href="#1">Bikes</a></li>  
                <li><a class="cars" href="#2">Cars</a></li>
                @if (ViewBag.MenuTypes.Contains("3"))
                {
                   <li><a class="Trucks" href="#3">Trucks</a></li>
               }

            </ul>
</div>

but on both cases I am getting: RunTimeBinderException was unhandled by user code Cannot perform runtime binding on a null reference.

I got it to work like this:

<add key="TrucksEnabled" value="true"/>

<div>  
            <ul id="setThemUp" class="tabs">  
                <li><a class="bikes" href="#1">Bikes</a></li>  
                <li><a class="cars" href="#2">Cars</a></li>
                @if ((bool)ViewBag.TrucksEnabled)
                {
                   <li><a class="Trucks" href="#3">Trucks</a></li>
               }

            </ul>
</div>

But I cant use it this way. I need it to work like in first example. I am not that good with Razor/MVC. Any help is appreciated.

Upvotes: 2

Views: 1011

Answers (4)

EnterpriseXL
EnterpriseXL

Reputation: 477

Folks, all of the examples were great, and showed me great learning material and options. After carefully looking at the examples you provided, I have found another solution that I plan to use. And it is dead simple:

<div>  
            <ul id="setThemUp" class="Vehicles">  
                <li><a class="bikes" href="#1">Bikes</a></li>  
                <li><a class="cars" href="#2">Cars</a></li>
                @{string options = System.Configuration.ConfigurationManager.AppSettings["MenuTypes"];

                  if (options.IndexOf("3") > -1) 
                 {
                   <li><a class="trucks" href="#3">Trucks</a></li>
                 }
                }
            </ul>
 </div>

What do you think about this approach?

Upvotes: 0

Moby&#39;s Stunt Double
Moby&#39;s Stunt Double

Reputation: 2550

I personally think you might be approaching this from the wrong angle, i.e. view-led logic rather than business logic. You want your view to be ignorant of all of this, really. What I would propose is to create some kind of storage, like an enum:

    public enum MenuType
    {
        Cars = 1,
        Trucks = 3
    }

Then have an static method like so:

public static class MenuFunctions
{
    public static bool ShowMenu(MenuType menuType)
    {
        bool showMenu = false;
        string appSetting = ConfigurationManager.AppSettings["YourKey"];
        if (!String.IsNullOrEmpty(appSetting))
            showMenu = appSetting.Contains("/" + (int)menuType.ToString() + "/");

        return showMenu;
    }

}

With your razor usage being:

@if(MenuFunctions.ShowMenu(MenuType.Trucks)
{
    //do truck menu
}

And your app setting being set up like so:

<add key = "YourKey" value = "/1/2/3/" />

Or with whichever delimiter you decided on. You could split the items into an array and over into an int, for a more accurate comparison within the static function, but you get my drift.

Benefits of this approach:

  1. Your view is ignorant of the logic.
  2. It will gracefully fail server side if you wrap it in a try block and you can catch and log exceptions where appropriate rather than having your view explode.
  3. You're dealing in set types at design time with the Enum. Take a menu out and you'll know at build where you've gone wrong, not at runtime in QA or worse.
  4. Much more maintainable, as you aren't using Dynamics layered on top of config that may or may not be present.

I hope this helps.

Upvotes: 1

Andy T
Andy T

Reputation: 9881

Controller

var menuTypes = WebConfigurationManager.AppSettings["MenuTypes"].ToString())
string[] tokens = menuTypes.Split(','); //Convert the strings into an array
ViewBag.MenuTypes = tokens;

View -- MenuTypes is now a list, so you can now use Contains():

@if (ViewBag.MenuTypes.Contains("3"))
{
     <li><a class="Trucks" href="#3">Trucks</a></li>
}

Upvotes: 1

Madax
Madax

Reputation: 377

You have more possibilities to better resolve this issue, maybe in a more controlled way.

You can maybe create an ActionFilter and decorate the main controller (or other controllers that you need this property) to read the application key (like WebConfigurationManager.AppSettings["PFUserName"].ToString() )

That way you have more control and behavior setting over the ViewBag.

Another solution, is if you have a baseController, you can set a property to read this app Key, although only if you need in your entire application.

OOrrr, if you need it only on one action, then the best is to simplify and set the ViewBag in there.

Upvotes: 0

Related Questions