TheDude TheDude - 1 month ago 7
ASP.NET (C#) Question

Correct way to have site-wide common properties in asp.net MVC 4?

Short question: what's the proper way to have common, site-wide, properties that are:


  1. Accessible in both
    _layout.cshtml
    and other views

  2. Strongly typed, ie. Model.TextInUserLanguage



And at the same time still allows custom controllers to their own model?

In other words, how to tell asp.net to:


  1. Use
    CommonModel
    with
    _layout.cshtml
    by default

  2. When accessing a controller C that has its own model M / view V, apply model M to view V (while still respecting rule #1)






Long story

I created a sample asp.net MVC 4 webapp, which has the
HomeController
and
AccountController
by default

HomeController.cs

public ActionResult Index()
{
CommonModel Model = new CommonModel { PageTitle = "HomePage" };
return View(Model);
}


BaseModel.cs

public abstract class BaseModel
{
public string AppName { get; set; }

public string Author { get; set; }

public string PageTitle { get; set; }

public string MetaDescription { get; set; }

...
}


CommonModel.cs

public class CommonModel: BaseModel
{
public CommonModel()
{
AppName = Properties.Settings.Default.AppName;
Author = Properties.Settings.Default.Author;
MetaDescription = Properties.Settings.Default.MetaDescription;
}
}


_layout.cshtml

@model K6.Models.BaseModel

<!DOCTYPE html>
<html>
<head>
<title>@Model.PageTitle - @Model.AppName</title>
...





The problem is, this approach:


  1. Really feels hacky

  2. I have to change every controller in my webapp so that they use this
    CommonModel
    in order to make
    _layout.cshtml
    recognize my custom properties, but at the same time this requires significant work in order to make things work when dealing HTTP Posts, showing lists, etc...



There must be other way to do this. I'm new to asp.net MVC, so what's the best way to do this about having to use
ViewBag
?

Answer

The first that comes to mind for me is something static

public static class ServerWideData {
    private static Dictionary<string, Data> DataDictionary { get; set; } = new Dictionary<string, Data>();

    public static Data Get(string controllerName = "") { // Could optionally add a default with the area and controller name
        return DataDictionary[controllerName];
    }
    public static void Set(Data data, string name = "") {
        DataDictionary.Add(name, data);
    }

    public class Data {
        public string PropertyOne { get; set; } = "Value of PropertyOne!!";
        // Add anything here
    }
}

You can add data from anywhere by calling

    ServerWideData.Set(new Data() { PropertyOne = "Cheese" }, "Key for the data")

And retrieve it anywhere with

    ServerWideData.Get("Key for the data").PropertyOne // => Cheese