2012-12-05 62 views
1

我有一个区域的MVC 3项目,我们称之为MyArea。我想放置特定于该区域的子文件夹下MyArea脚本和样式,导致项目文件夹结构是这样的:路由MVC区域内容与控制器和操作相同吗?

/Areas/MyArea 
/Areas/MyArea/Controllers 
/Areas/MyArea/Scripts <-------- I want these here 
/Areas/MyArea/Styles <-------- 
/Areas/MyArea/ViewModels 
/Areas/MyArea/Views 
/Controllers 
/Scripts 
/Styles 
/ViewModels 
/Views 

精细,但现在当我链接到样式的文档/视图它必须这样写的:

<link href="/Areas/MyArea/Styles/MyStyle.css" rel="stylesheet" type="text/css" /> 

我宁愿像这样链接:

<link href="/MyArea/Styles/MyStyle.css" rel="stylesheet" type="text/css" /> 

这将是相同的路由,作为该地区的countrollers和行动。

我该如何实现这个路由?

+0

检查此解决方案:http://stackoverflow.com/questions/5130226/relative-content-path-in-mvc3-areas –

回答

3

在研究了Behnam Esmaili提到的问题之后,进一步阅读,进一步阅读和进一步阅读:-)这就是我想出的。

我创建了一个新的IHttpModule用于检查/areaname/contentfolder/每个进来的请求,其中areaname是任何应用程序的领域名称的路径,contentfolder是任何可能的内容的文件夹名称的选择列表。我选择了硬编码一组合理的内容文件夹名称,但是您可以让每个区域注册将其所有内容文件夹名称注册到某处并使用它。

注意:联机Microsoft文档Walkthrough: Creating and Registering a Custom HTTP Module建议您将HTTPModule类放在App_Code文件夹中。别!该文件夹中的类由ASP.Net进行运行时编译,导致临时.Net文件夹中的类的临时副本,这反过来在ASP.Net尝试加载HTTPModule类时引起歧义。将课程放置在您选择的不同文件夹中。

要查找所有地区名称,我选择使用AppDomain.CurrentDomain.GetAssemblies()并查找System.Web.Mvc.AreaRegistration的所有子类别。创建每个实例并检索其AreaName属性的值。

完整的源代码:

public class HTTPModuleAreaContent : IHttpModule 
{ 
    private List<string> allAreaNames = null; 

    public HTTPModuleAreaContent() 
    { 
    } 

    public String ModuleName 
    { 
     get { return "HTTPModuleAreaContent"; } 
    } 

    public void Init(HttpApplication application) 
    { 
     application.BeginRequest += 
      (new EventHandler(this.BeginRequest)); 
    } 

    private void GetAreaNames(HttpContext context) 
    { 
     allAreaNames = AppDomain.CurrentDomain.GetAssemblies() 
      .SelectMany(ass => ass.GetTypes()) 
      .Where(t => t.IsSubclassOf(typeof(AreaRegistration))) 
      .Select(t => ((AreaRegistration)Activator.CreateInstance(t)).AreaName) 
      .ToList(); 
    } 

    private void BeginRequest(object sender, EventArgs e) 
    { 
     HttpApplication application = (HttpApplication)sender; 
     HttpContext context = application.Context; 
     if (allAreaNames == null) 
      GetAreaNames(context); 

     string filePath = context.Request.FilePath.ToUpper(); 
     string areaName = allAreaNames 
      .FirstOrDefault(an => filePath.StartsWith('/' + an + '/', StringComparison.OrdinalIgnoreCase)); 
     if (string.IsNullOrEmpty(areaName)) 
      return; 
     string areaNameUpper = areaName.ToUpper(); 
     if (filePath.StartsWith('/' + areaNameUpper + "/STYLES/") 
      || filePath.StartsWith('/' + areaNameUpper + "/SCRIPT/") 
      || filePath.StartsWith('/' + areaNameUpper + "/SCRIPTS/") 
      || filePath.StartsWith('/' + areaNameUpper + "/JS/") 
      || filePath.StartsWith('/' + areaNameUpper + "/JAVASCRIPT/") 
      || filePath.StartsWith('/' + areaNameUpper + "/JAVASCRIPTS/") 
      || filePath.StartsWith('/' + areaNameUpper + "/CONTENT/") 
      || filePath.StartsWith('/' + areaNameUpper + "/IMAGES/") 
     ) 
      context.RewritePath("/Areas/" + context.Request.Path); 
    } 

    public void Dispose() { } 
} 

编辑:显然,上述溶液中不为吃不是在域的根应用程序的工作。一些工作后,我想出了以下解决方案,而不是:

public class HTTPModuleAreaContent : IHttpModule 
{ 
    private List<string> allAreaNames = null; 
    private HashSet<string> folderNamesToRewrite = new HashSet<string>(); 

    public HTTPModuleAreaContent() 
    { 
    } 

    public String ModuleName 
    { 
     get { return "HTTPModuleAreaContent"; } 
    } 

    public void Init(HttpApplication application) 
    { 
     application.BeginRequest += 
      (new EventHandler(this.BeginRequest)); 
     folderNamesToRewrite.Add("STYLES"); 
     folderNamesToRewrite.Add("SCRIPT"); 
     folderNamesToRewrite.Add("SCRIPTS"); 
     folderNamesToRewrite.Add("JS"); 
     folderNamesToRewrite.Add("JAVASCRIPT"); 
     folderNamesToRewrite.Add("JAVASCRIPTS"); 
     folderNamesToRewrite.Add("CONTENT"); 
     folderNamesToRewrite.Add("IMAGES"); 
    } 

    private void GetAreaNames(HttpContext context) 
    { 
     allAreaNames = AppDomain.CurrentDomain.GetAssemblies().SelectMany(ass => ass.GetTypes()).Where(t => t.IsSubclassOf(typeof(AreaRegistration))).Select(t => ((AreaRegistration)Activator.CreateInstance(t)).AreaName).ToList(); 
    } 

    private void BeginRequest(object sender, EventArgs e) 
    { 
     HttpApplication application = (HttpApplication)sender; 
     HttpContext context = application.Context; 
     if (allAreaNames == null) 
      GetAreaNames(context); 

     string filePath = context.Request.FilePath; 
     string areaName = allAreaNames.FirstOrDefault(an => Regex.IsMatch(filePath, '/' + an + '/', RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)); 
     if (string.IsNullOrEmpty(areaName)) 
      return; 
     string areaNameUpper = areaName.ToUpperInvariant(); 
     Regex regex = new Regex('/' + areaNameUpper + "/([^/]+)/", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); 
     Match m = regex.Match(filePath); 
     if (m.Success && m.Groups.Count > 1) 
     { 
      string folderName = m.Groups[1].Value; 
      string folderNameUpper = folderName.ToUpperInvariant(); 
      if (folderNamesToRewrite.Contains(folderNameUpper)) 
       context.RewritePath(regex.Replace(context.Request.Path, string.Format("/Areas/{0}/{1}/", areaName, folderName), 1)); 
     } 
    } 

    public void Dispose() { } 
相关问题