简体   繁体   中英

Use global variable in ASP.NET MVC

First look at the sample controller code. There you'll find two statements which are repetitive-

public class DashboardController : Controller
{
    //the following line is repetitive for every controller.
    String ConnectionString = WebConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
    public ActionResult Index()
    {
        try
        {
            //codes
        }
        catch (Exception Ex)
        {
            //The following line is repetitive for every action method.
            var path = HttpContext.Server.MapPath("~/App_Data");
            ExceptionLog.Create(Ex, path);
        }
        return View("AdminDashboard");
    }
}

I would like to avoid such repetition. Is there any way to do it which can work for the entire application as global variable?

If it were me, and there were frequent configuration options I needed to access, I would create/expose some kind of IAppConfiguration which I could drop in to my controllers (using dependency injection). Something like:

public interface IAppConfguration
{
    String MyConnectionString { get; }
    String ServerPath { get; }
}
public class AppConfiguration : IAppConfiguration
{
    private readonly HttpContext context;
    public AppConfiguration(HttpContext context)
    {
        this.context = context;
    }

    public String MyConnectionString
    {
        get { return COnfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
    }
    public String ServerPath
    {
        get { return context.Server.MapPath("~/"); }
    }
}

Then you can extend it for different circumstances, sub-sites/areas, etc. Then, bring it in via the controller's constructor:

public class MyController : Controller
{
    private readonly IAppConfiguration config;
    public MyController()
        : this(new AppConfiguration(HttpContext.Current))
    {
    }
    public MyController(IAppConfiguration config)
    {
        this.config = config;
    }

    // reference config.ServerPath or config.MyConnectionString;
}

Taking it a step further, you could add a factory atop this, bring that in as a reference instead, and allow you to get configuration settings for other environments. eg

IAppConfiguration config = configFactory.GetConfig(/* environment */);

The thing I like about this approach is allows me to substitute out settings for local [unit/integration] testing. Using base controllers/static classes would make it very difficult to substitute out these values at a later time.

Here is an example using a base controller approach:

public abstract class BaseController : Controller
{
    protected string ConnectionString = WebConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;

    protected void LogException(Exception ex)
    {
        var path = HttpContext.Server.MapPath("~/App_Data");
        ExceptionLog.Create(Ex, path);
    }    
}

public class DashboardController : BaseController
{
    public ActionResult Index()
    {
        try
        {
            string conn = base.ConnectionString;
            //codes
        }
        catch (Exception ex)
        {
            base.LogException(ex);
        }
        return View("AdminDashboard");
    }
}

To avoid exception catching you can log it in OnError event handler in global.asax.cs:

protected void Application_Error(object sender, EventArgs e)
{
    HttpContext ctx = HttpContext.Current;

    Exception ex = ctx.Server.GetLastError();

    var path = HttpContext.Server.MapPath("~/App_Data");
    ExceptionLog.Create(Ex, path);
}

you can use connection string name "MyConnectionString" instead of WebConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString when pass it to dbcontext or ADO Connection.

But more rightful way is to inject (with Dependency Injection) in controller class that will be responsible for work with database instead of creating it in controller and passing there connection string.

You can inherit controller and then use it for all other controllers, have a look at similar question How can I inherit an ASP.NET MVC controller and change only the view? .

But this will be only accessible in controllers, you can also create a class with static method or property returning back the connection string. This can be used in any path of code where you have access to the class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM