1

エリアを持つ MVC 3 プロジェクトがあります。それを MyArea と呼びましょう。MyArea に固有のスクリプトとスタイルをその領域のサブフォルダーの下に配置すると、次のようなプロジェクト フォルダー構造になります。

/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" />

これは、エリアのカウンターローラーとアクションと同じルーティングになります。

このルーティングを実現するにはどうすればよいですか?

4

1 に答える 1

3

Behnam Esmaili によって言及された質問を調査し、さらに、さらに、さらに読んでください :-) これが私が思いついたものです。

/areaname/contentfolder/各受信要求のパスをチェックする新しい IHttpModule を作成しましareanamecontentfolder。もっともらしいコンテンツ フォルダー名のセットをハードコードすることにしましたが、各エリア登録ですべてのコンテンツ フォルダー名をどこかに登録し、それを使用することができます。

注: オンラインの Microsoft ドキュメントウォークスルー: カスタム HTTP モジュールの作成と登録では、HTTPModule クラスを App_Code フォルダーに配置することをお勧めします。しないでください!そのフォルダー内のクラスは、ASP.Net によってランタイム コンパイルされます。その結果、temp .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() { }
于 2012-12-06T10:36:31.407 に答える