使用子域作为参数

本文关键字:参数 | 更新日期: 2023-09-27 18:30:49

我有一个 ASP.net MVC (5.2)站点,它使用多个子域运行,其中子域的名称是我的数据库中客户端的名称。基本上,我想做的是将子域用作操作方法中的变量,以允许我从数据库中获取正确的数据。

几年前我做了类似的事情,但它很混乱,不直观,所以想知道是否有比我以前使用更好的方法。这是我之前做的:

protected override void OnActionExecuting(ActionExecutingContext filterContext) {
    Session["subdomain"] = GetSubDomain(Request.Url);
}
private static string GetSubDomain(Uri url) {
    string host = url.Host;
    if (host.Split('.').Length > 1) {
        int index = host.IndexOf(".");
        string subdomain = host.Substring(0, index);
        if (subdomain != "www") {
            return subdomain;
        }
    }
    return null;
}

如果子域不是"www",则基本上为会话变量分配了一个键,但我真的对这种方式不满意,因为它依赖于我知道会话可能包含这个神奇的值!

理想情况下,我希望能够创建一个属性,我可以用该属性来装饰我的类/方法,该属性将提取子域,然后允许我在操作方法中包含"子域"参数,该参数将包含属性提取的值。这可能吗?

如果无法做到这一点,是否有更好的方法来做我现在正在做的事情而不必依赖会话?

谢谢

迪伦

使用子域作为参数

你的权利不需要存储在会话中,恕我直言不应该,我会把它重构成它自己的类并使用HttpContext.Current

public interface ISubDomainProvider
{
    string SubDomain { get; set; }
}

public class SubDomainProvider : ISubDomainProvider
{
    public SubDomainProvider()
    {
        string host = HttpContext.Current.Request.Url.Host; // not checked (off the top of my head
        if (host.Split('.').Length > 1) 
        {
            int index = host.IndexOf(".");
            string subdomain = host.Substring(0, index);
            if (subdomain != "www") 
            {
                SubDomain = subdomain;
            }
        }
    }
    public string SubDomain { get; set; }
}

你选择如何使用它,如果你使用 IoC 容器,它只是通过构造函数将这个类注入你的控制器的情况,我喜欢这个,因为它更容易模拟和单元测试。当然,您仍然可以这样做:

public class SomeController : Controller
{
    private readonly ISubDomainProvider _subDomainProvider;
    public SomeController()
    {
        _subDomainProvider = new SubDomainProvider();
    }
} 

您甚至可以创建自己的抽象控制器类:

public abstract class MyAbstractController : Controller
{
    public MyAbstractController()
    {
        SubDomain = new SubDomainProvider();
    }
    protected string SubDomain {get; set; }
}
public class SomeController : MyAbstractController
{
    public ActionResult SomeAction()
    {
        // access the subdomain by calling the base base.SubDomain 
    }
}

您可以在global.asax Session_Start事件的Session中设置名称,这意味着它只会发生一次,并且会在用户会话期间持续存在

public void Session_Start(object sender, EventArgs e)
{
    Session["subdomain"] = GetSubDomain(Request.Url);
}

看起来有一个很好的方法来做我所追求的事情:

ASP.NET MVC 传递对象从自定义操作筛选器传递到操作

它本质上使用路由数据将自定义参数传递给操作,也可以传递简单字符串等以外的对象。

从好的方面来说,它避免使用会话并依赖魔术值,但缺点是它意味着处理每个请求的URL,如果涉及数据库,这可能不是一个好主意。