우리는 기존의 WebForms 구현으로 현재 프레임 워크 사이트의 Mvc3 구현 작업을 시작했습니다.구조체 맵을 사용하여 앱의 코어 내에서 일반적인 경로 결정하기 IoC
이 작업을 통해 유연성을 위해 IoC와 DI를 Structuremap과 통합 할 수있었습니다.
당신에게 몇 가지 배경을 제공하기 위해, 우리는 다음과 같은 프로젝트 구조를 가지고 :
App.Core < - 코어 클래스 라이브러리
App.Mvc < - MVC 클래스 라이브러리
App.Mvc.Web < - Mvc3 APP
App.WebForms < - 웹 양식 클래스 라이브러리
App.WebForms.Web < - 웹 양식 응용 프로그램 또는 사이트
우리는 Mvc와 WebForms 구현 모두에서 Mvc의 라우팅을 사용하고 있습니다. IRouteProvider를 사용하여 Orchard 프로젝트에서와 같이 경로 게시에 동일한 방법을 사용했습니다. N 개의 IRouteProvider 구현을 만들어서 게시자는 자신의 우선 순위에 따라 등록 및 주문할 수 있습니다.
정상적으로 작동합니다. MVC의 UrlHelper 또는 WebForms의 Page.GetRouteUrl을 사용하여 경로를 등록하고 사용할 수 있습니다.
문제는 App.Core가 이러한 경로 (모든 경로가 아닌 일부 경로)를 해결할 수 있어야하며 구현되는 사이트에 따라 변경 될 수 있다는 것입니다. .
예를 들어, 제품 세부 경로 기본 경로는 "/ {category}/{product_name}/{product_id}"일 수 있지만이를 무시하고 특정 사이트의 경우 "/ {brand}/{product_name }/{product_id} "대신 사용하십시오.
즉, 코어에서 RouteTable.Routes.GetVirtualPath를 고정 된 매개 변수 집합으로 사용하는 것은 사이트간에 변경 될 수 있기 때문에 가능하지 않습니다.
가장 일반적인 경로에 대한 메서드를 사용하여 IRouteResolver 인터페이스를 만들었습니다.이 인터페이스는 각 클래스 라이브러리 (Mvc 또는 Webforms)의 SM에 등록되어 있지만 각 사이트에서 재정의 될 수도 있습니다.
이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)));
}
}
이
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);
}
인터페이스의 기본 MVC 구현은 다음과 같습니다처럼
인터페이스 본다 그 때문에 생성자 인수 (UrlHelper에 대한 Mvc 및 페이지 또는 컨트롤 t 그는 Webforms입니다) 우리는 SM을 사용하지 않고 IRouteResolver 플러그인의 인스턴스를 잡는 대신 구체적인 유형을 사용해야합니다.예를 들어
나는 우리가 특별히에 대한 해결을 오버라이드 (override) 할 때 웹 또는 MVC가 아닌 경우에 대한 기본 동작을 포함
public static IRouteResolver RouteResolver(this Control control)
{
return new WebRouteResolver(control);
}
public static IRouteResolver RouteResolver(this Page page)
{
return new WebRouteResolver(page);
}
페이지 또는 제어에 대한 해결 사용할 수 있도록 다음과 같은 확장이 사이트 당 기준.
질문 : 이러한 생성자 인수를 SM에 플러그인으로 추가하는 것이 안전합니까?
이 기능 요청에 대해 권장 할 수있는 또 다른 접근 방식이나 패턴이 있습니까?
모든 아이디어/제안을 주시면 감사하겠습니다.
많은 감사, P.
는 (A SM 레지스트리 클래스를 사용을 위해 설정하여 각 클래스 라이브러리에서 수행 된 IRouteResolver에 대한 SM에 언급 등록을 잊었다). ();를 사용하십시오. –