現在、私たちは既存のWebForms実装を使用して、フレームワークサイトのMvc3実装を行うという使命に着手しました。構造マップを使用してアプリケーションのコア内で一般的なルートを解決するIoC
このタスクでは、柔軟性のためにIoCとDIをStructure Mapと統合することができました。
はあなたにいくつかの背景を与えるために、私たち次のプロジェクトの構造を有する:
App.Core < - コアクラスライブラリ
App.Mvc < - MVCクラスライブラリ
App.Mvc.Web < - Mvc3 APP
App.WebForms < - Webフォームクラスライブラリ
App.WebForms.Web < - Webフォームアプリやサイト
私たちはMvcとWebFormsの両方の実装でMvcのルーティングを使用しています.IRouteProviderを使用してOrchardプロジェクトと同じ方法でルートパブリッシングを行いました.IRouteProviderのN個の実装を作成して出版社はその優先順位によって登録し、注文する。
これは正常に動作しており、WebフォームのMVCまたはPage.GetRouteUrlのUrlHelperでルートを登録して使用することができます。
問題は、App.Coreがこれらのルート(すべてではなく一部の最も一般的なルート)を解決できるようになり、実装されているサイトに応じて変更できるということです。 。
たとえば、商品の詳細なデフォルトルートは「/ {category}/{product_name}/{product_id}」ですが、これを上書きして特定のサイトに対しては「/ {brand}/{product_name }/{product_id} "となります。
これは、コアでは、RouteTable.Routes.GetVirtualPathを固定パラメータセットで使用するだけでは、サイト間で変更される可能性があるためです。
最も一般的なルートのメソッドを持つIRouteResolverインターフェイスを作成しました。このインターフェイスは、各クラスライブラリ(MvcまたはWebforms)でSMに登録されているデフォルト実装を持ちますが、各サイトでオーバーライドすることもできます。
のようにインターフェースが見えます:デフォルトのWebフォームの実装がどのように見える
public class MvcRouteResolver : IRouteResolver
{
UrlHelper _urlHelper;
ICategoryModelBroker _categoryModelBroker;
IBrandModelBroker _brandModelBroker;
IProductModelBroker _productModelBroker;
public MvcRouteResolver(UrlHelper urlHelper)
{
_urlHelper = urlHelper;
_categoryModelBroker = ObjectFactory.GetInstance<ICategoryModelBroker>();
_brandModelBroker = ObjectFactory.GetInstance<IBrandModelBroker>();
_productModelBroker = ObjectFactory.GetInstance<IProductModelBroker>();
}
public string GetRouteUrl(object routeParameters)
{
return GetRouteUrl(new RouteValueDictionary(routeParameters));
}
public string GetRouteUrl(System.Web.Routing.RouteValueDictionary routeParameters)
{
return GetRouteUrl(null, new RouteValueDictionary(routeParameters));
}
public string GetRouteUrl(string routeName, object routeParameters)
{
return GetRouteUrl(routeName, new RouteValueDictionary(routeParameters));
}
public string GetRouteUrl(string routeName, System.Web.Routing.RouteValueDictionary routeParameters)
{
return _urlHelper.RouteUrl(routeName, routeParameters);
}
public string GetUrlFor(Product product)
{
string category = string.Empty;
if (product.Categories.Count > 0)
category = product.Categories[0].Breadcrumb.Replace("@@", "-");
else if (product.Brands.Any())
category = product.Brands.FirstOrDefault().Name;
else
category = "detail";
return GetRouteUrl(new { controller="Product", action="Detail", productId = product.Id, brandName = _productModelBroker.GetSlug(product), productName = _productModelBroker.GetSluggedName(product) });
}
public string GetUrlFor(Category category)
{
return GetRouteUrl(new { controller = "Product", action = "ListByCategory", id = category.Id, name = _categoryModelBroker.GetSlug(category) });
}
public string GetUrlFor(Brand brand)
{
return GetRouteUrl(new { controller = "Product", action = "ListByBrand", id = brand.Id, name = _brandModelBroker.GetSlug(brand) });
}
}
:
public class WebRouteResolver : IRouteResolver
{
Control _control;
HttpContext _context;
public WebRouteResolver()
:this(HttpContext.Current)
{
}
public WebRouteResolver(HttpContext context)
{
_context = context;
}
public WebRouteResolver(Control control)
{
_control = control;
}
public WebRouteResolver(Page page)
{
_control = page as Control;
}
public string GetRouteUrl(object routeParameters)
{
return GetRouteUrl(new RouteValueDictionary(routeParameters));
}
public string GetRouteUrl(System.Web.Routing.RouteValueDictionary routeParameters)
{
return GetRouteUrl(null, new RouteValueDictionary(routeParameters));
}
public string GetRouteUrl(string routeName, object routeParameters)
{
return GetRouteUrl(routeName, new RouteValueDictionary(routeParameters));
}
public string GetRouteUrl(string routeName, System.Web.Routing.RouteValueDictionary routeParameters)
{
VirtualPathData virtualPath = null;
if(_control.IsNotNull())
virtualPath = RouteTable.Routes.GetVirtualPath(_control.Page.Request.RequestContext, routeName, routeParameters);
else
virtualPath = RouteTable.Routes.GetVirtualPath(_context.Request.RequestContext, routeName, routeParameters);
if (virtualPath != null)
{
return virtualPath.VirtualPath;
}
return null;
}
private string ResolveUrl(string originalUrl)
{
if(_control.IsNotNull())
return _control.ResolveUrl(originalUrl);
// *** Absolute path - just return
if (originalUrl.IndexOf("://") != -1)
return originalUrl;
// *** Fix up image path for ~ root app dir directory
if (originalUrl.StartsWith("~"))
{
string newUrl = "";
if (_context != null)
newUrl = _context.Request.ApplicationPath +
originalUrl.Substring(1).Replace("//", "/");
else
// *** Not context: assume current directory is the base directory
throw new ArgumentException("Invalid URL: Relative URL not allowed.");
// *** Just to be sure fix up any double slashes
return newUrl;
}
return originalUrl;
}
public string GetUrlFor(Product product)
{
string category = string.Empty;
if (product.Categories.Count > 0)
category = product.Categories[0].Breadcrumb.Replace("@@", "-");
else if (product.Brands.Any())
category = product.Brands.FirstOrDefault().Name;
else
category = "detail";
if (Config.RoutingEnabled)
{
return GetRouteUrl(new { @category = CommonHelper.ToFriendlyUrl(category), name = CommonHelper.ToFriendlyUrl(product.Name), id = product.Id });
}
return ResolveUrl(Config.GetStoreSetting("productDetailUrl")) + "?id={0}&name={1}&category={2}".Fill(product.Id, CommonHelper.ToFriendlyUrl(product.Name), CommonHelper.ToFriendlyUrl(category));
}
public string GetUrlFor(Category category)
{
string breadcrumb = category.Breadcrumb.Replace("@@", "-");
if (Config.RoutingEnabled)
return GetRouteUrl(new { @category = CommonHelper.ToFriendlyUrl(breadcrumb), category_id = category.Id});
return ResolveUrl(Config.GetStoreSetting("productListingUrl") + "?category_id={0}&category={1}".Fill(category.Id, CommonHelper.ToFriendlyUrl(category.Name)));
}
public string GetUrlFor(Brand brand)
{
if (Config.RoutingEnabled)
return GetRouteUrl(new { @brand = CommonHelper.ToFriendlyUrl(brand.Name), brand_id = brand.Id });
return ResolveUrl(Config.GetStoreSetting("productListingUrl") + "?brand_id={0}&brand={1}".Fill(brand.Id, CommonHelper.ToFriendlyUrl(brand.Name)));
}
}
問題は今のようなインターフェースのデフォルトのMVCの実装が見え
public interface IRouteResolver
{
string GetRouteUrl(object routeParameters);
string GetRouteUrl(RouteValueDictionary routeParameters);
string GetRouteUrl(string routeName, object routeParameters);
string GetRouteUrl(string routeName, RouteValueDictionary routeParameters);
string GetUrlFor(Product product);
string GetUrlFor(Category category);
string GetUrlFor(Brand brand);
}
その理由は、コンストラクタの引数(UrlHelperは、Mvcとページまたはコントロールのt彼はWebformsを使用しています)、IRを使用してIRouteResolverプラグインのインスタンスを取得するのではなく、具体的なタイプを使用する必要があります。例えば
私はページ上のリゾルバを使用可能にするには、以下の拡張子を持っているか、コントロール
public static IRouteResolver RouteResolver(this Control control)
{
return new WebRouteResolver(control);
}
public static IRouteResolver RouteResolver(this Page page)
{
return new WebRouteResolver(page);
}
これは、既定のWebまたはMVCのための行動ではなく、我々は、具体的にリゾルバを上書きしたい場合をカバーサイトごとに
SMにプラグインとしてこれらのコンストラクタ引数を追加するのは安全ですか?
この機能のリクエストに推奨できる別のアプローチ/パターンはありますか?
ご意見やご提案をいただければ幸いです。
多くのおかげで、 P.
は言及を忘れてしまった、IRouteResolverのためのSMの登録は(SMレジストリクラスを使用して、のために設定することにより、各クラスライブラリ上で行われます)。();を使用します。 –