0

少し問題があります。Framed という領域があります。このエリアにはホームコントローラーがあります。サイトのデフォルトには、ホーム コントローラーもあります。

私がこれでやろうとしているのは、IFrame に適した各コントローラー/アクションのバージョンと、通常のサイトのバージョンを用意することです。私はこれをマスター ページで行います。サイト マスターページには、フレーム バージョンとは異なる多くのコンテンツ プレース ホルダーがあります。このため、マスター ページを入れ替えることはできません。たとえば、http://example.com/Framed/Account/Indexは、外部サイトで使用するアカウント情報のみを含む非常に基本的なバージョンを表示します。 http://example.com/Account/Indexは同じデータを表示しますが、デフォルト サイト内にあります。

私の IoC コンテナーは構造マップです。それで、http ://odetocode.com/Blogs/scott/archive/2009/10/19/mvc-2-areas-and-containers.aspxとhttp://odetocode.com/Blogs/scott/archive/を見つけました2009/10/13/asp-net-mvc2-preview-2-areas-and-routes.aspx . これが私の現在のセットアップです。

構造マップ初期化

ObjectFactory.Initialize(x =>
            {
                x.AddRegistry(new ApplicationRegistry());
                x.Scan(s =>
                {
                    s.AssembliesFromPath(HttpRuntime.BinDirectory);
                    s.AddAllTypesOf<IController>()
                        .NameBy(type => type.Namespace + "." + type.Name.Replace("Controller", ""));
                });
            });

ここでデバッグ中に見つかった問題は、コントローラーが同じ名前 (HomeController) を持っているため、最初のコントローラーのみが登録され、これがデフォルトのホーム コントローラーであるということです。すべてのコントローラーが登録されるように、クリエイティブになり、名前空間を追加しました。

デフォルトルート

routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { area = "", controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
                new[] { "MySite.Controllers" }
                );

エリアルート

context.MapRoute(
                "Framed_default",
                "Framed/{controller}/{action}/{id}",
                new { area = "Framed", controller = "Home", action = "Index", id = UrlParameter.Optional },
                new string[] { "MySite.Areas.Framed.Controllers" }
            );

Phil Haackの推奨に従って、名前空間を 4 番目のパラメーターとして使用しています。

初期化の順序を証明するためだけに、アプリの開始

protected void Application_Start()
        {
            InitializeControllerFactory();

            AreaRegistration.RegisterAllAreas();

            RouteConfiguration.RegisterRoutes();
        }

コントローラーファクトリー

protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            IController result = null;
            if (controllerType != null)
            {
                result = ObjectFactory.GetInstance(controllerType)
                    as IController;
            }
            return result;
        }

そのため、/Home/Index を押すと、正しいコントローラー タイプが渡されます。/Framed/Home/Index をヒットすると、controllerType が null になり、コントローラーが返されないためエラーになります。

MVC が私の領域を完全に無視しているかのようです。何が起きてる?私は何を間違っていますか?

4

2 に答える 2

0

AreasでStructuremapを使用して同様の問題が発生しました。Adminという名前のエリアがあり、/ adminに移動しようとすると、コントローラータイプがnullのStructureMapコントローラーファクトリに到達します。

このブログ投稿に従って修正しました: http ://stephenwalther.com/blog/archive/2008/08/07/asp-net-mvc-tip-30-create-custom-route-constraints.aspx

コントローラが管理者である場合に一致しないようにデフォルトルートに制約を追加する必要がありました。

これが私のデフォルトルートの定義です:

routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "MyController", action = "AnAction", id = UrlParameter.Optional },
    new { controller = new NotEqualConstraint("Admin")},
    new string[] {"DailyDealsHQ.WebUI.Controllers"} 
);

NotEqualConstraintの実装は次のとおりです。

public class NotEqualConstraint : IRouteConstraint
{
    private string match = String.Empty;

    public NotEqualConstraint(string match)
    {
        this.match = match;
    }

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        return String.Compare(values[parameterName].ToString(), match, true) != 0;
    }
}

この問題を解決する方法はおそらく他にもありますが、これで修正されました:)

于 2010-10-26T22:56:27.607 に答える
0

誰かが同様のことをしようとした場合に備えて、私はこの投稿のアイデアを使用しました: MVC ルーティングのコントローラーのカテゴリ? (別の名前空間でのコントローラー名の重複)領域を使用して完全にダンプし、自分で何かを実装する必要がありました。

Controllers/HomeController.cs と Controllers/Framed/HomeController.cs があります

/Controllers のすべてのコントローラーが継承するクラス ControllerBase があります。/Controllers/Framed 内のすべてのコントローラーが拡張する ControllerBase から継承する AreaController があります。

これが私のエリアコントローラークラスです

public class AreaController : ControllerBase
    {
        private string Area
        {
            get
            {
                return this.GetType().Namespace.Replace("MySite.Controllers.", "");
            }
        }
        protected override ViewResult View(string viewName, string masterName, object model)
        {
            string controller = this.ControllerContext.RequestContext.RouteData.Values["controller"].ToString();

            if (String.IsNullOrEmpty(viewName))
                viewName = this.ControllerContext.RequestContext.RouteData.Values["action"].ToString();

            return base.View(String.Format("~/Views/{0}/{1}/{2}.aspx", Area, controller, viewName), masterName, model);
        }

        protected override PartialViewResult PartialView(string viewName, object model)
        {
            string controller = this.ControllerContext.RequestContext.RouteData.Values["controller"].ToString();

            if (String.IsNullOrEmpty(viewName))
                viewName = this.ControllerContext.RequestContext.RouteData.Values["action"].ToString();

            PartialViewResult result = null;

            result = base.PartialView(String.Format("~/Views/{0}/{1}/{2}.aspx", Area, controller, viewName), model);

            if (result != null)
                return result;

            result = base.PartialView(String.Format("~/Views/{0}/{1}/{2}.ascx", Area, controller, viewName), model);

            if (result != null)
                return result;

            result = base.PartialView(viewName, model);

            return result;
        }
    }

ビューとパーシャルビューのメソッドをオーバーライドする必要がありました。このようにして、私の「領域」のコントローラーは、ビューとパーシャルにデフォルトのメソッドを使用し、追加されたフォルダー構造をサポートできます。

ビューに関しては、Views/Home/Index.aspx と Views/Framed/Home/Index.aspx があります。投稿に示されているようにルーティングを使用しますが、参照用に私の検索方法を次に示します。

var testNamespace = new RouteValueDictionary();
            testNamespace.Add("namespaces", new HashSet<string>(new string[] 
            { 
                "MySite.Controllers.Framed"
            }));

            //for some reason we need to delare the empty version to support /framed when it does not have a controller or action
            routes.Add("FramedEmpty", new Route("Framed", new MvcRouteHandler())
            {
                Defaults = new RouteValueDictionary(new
                {
                    controller = "Home",
                    action = "Index",
                    id = UrlParameter.Optional
                }),
                DataTokens = testNamespace
            });

            routes.Add("FramedDefault", new Route("Framed/{controller}/{action}/{id}", new MvcRouteHandler())
            {
                Defaults = new RouteValueDictionary(new
                {
                    //controller = "Home",
                    action = "Index",
                    id = UrlParameter.Optional
                }),
                DataTokens = testNamespace
            });

var defaultNamespace = new RouteValueDictionary();
            defaultNamespace.Add("namespaces", new HashSet<string>(new string[] 
            { 
                "MySite.Controllers"
            }));

routes.Add("Default", new Route("{controller}/{action}/{id}", new MvcRouteHandler())
                {
                    Defaults = new RouteValueDictionary(new
                    {
                        controller = "Home",
                        action = "Index",
                        id = UrlParameter.Optional
                    }),
                    DataTokens = defaultNamespace
                });

これで、同じサイトの /Home/Index または /Framed/Home/Index に移動して、共有コントロールで 2 つの異なるビューを取得できます。理想的には、1 つのコントローラーが 2 つのビューのいずれかを返すようにしたいのですが、2 つのコントローラーなしでそれを機能させる方法がわかりません。

于 2010-10-15T21:07:47.423 に答える