我有一個問題,使OutputCaching與HttpContext.RewritePath
一起使用WCF 4.0 WebHttp服務。WCF休息4.0,動態路由和OutputCache
我的服務已本地化。這個想法是,你這樣稱呼一個URL:
/languageCode/ServiceName/Method
e.g.
/en/MyService/GetItems
它會返回結果本地化到正確的語言。
我的計劃基於this article。這個想法是創建一個RouteBase的衍生物,創建一個獨特的「私人」路線到真正的服務。當用戶提出請求時,語言代碼將從URL中解壓縮並設置爲當前線程的文化,然後HttpContext.RewritePath
用於加載實際服務。
對於我的生活,我無法弄清楚如何將OutputCaching加入混合。我用AspNetCacheProfile
裝飾了我的服務方法,並且看到我自己的VaryByCustom
覆蓋呼叫。儘管如此,儘管從VaryByCustom
收到重複的結果,.NET繼續進入我的服務方法。
下面有很多代碼,對於轉儲抱歉,但我懷疑它是所有相關的。
如何我的Global.asax.cs
RouteTable.Routes.Add(new CulturedServiceRoute(
"devices",
new StructureMapServiceHostFactory(),
typeof(DeviceService)));
VaryByCustom是覆蓋添加路由在Global.asax.cs中:
public override string GetVaryByCustomString(
HttpContext context, string custom)
{
// This method gets called twice: Once for the initial request, then a
// second time for the rewritten URL. I only want it to be called once!
if (custom == "XmlDataFreshness")
{
var outputString = String.Format("{0}|{1}|{2}",
XmlDataLoader.LastUpdatedTicks,
context.Request.RawUrl,
context.Request.HttpMethod);
return outputString;
}
return base.GetVaryByCustomString(context, custom);
}
這是動態服務路由類。
public class CulturedServiceRoute : RouteBase, IRouteHandler
{
private readonly string _virtualPath = null;
private readonly ServiceRoute _innerServiceRoute = null;
private readonly Route _innerRoute = null;
public CulturedServiceRoute(
string pathPrefix,
ServiceHostFactoryBase serviceHostFactory,
Type serviceType)
{
if (pathPrefix.IndexOf("{") >= 0)
{
throw new ArgumentException(
"Path prefix cannot include route parameters.",
"pathPrefix");
}
if (!pathPrefix.StartsWith("/")) pathPrefix = "/" + pathPrefix;
pathPrefix = "{culture}" + pathPrefix;
_virtualPath = String.Format("Cultured/{0}/", serviceType.FullName);
_innerServiceRoute = new ServiceRoute(
_virtualPath, serviceHostFactory, serviceType);
_innerRoute = new Route(pathPrefix, this);
}
public override RouteData GetRouteData(
HttpContextBase httpContext)
{
return _innerRoute.GetRouteData(httpContext);
}
public override VirtualPathData GetVirtualPath(
RequestContext requestContext, RouteValueDictionary values)
{
return null;
}
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
// This method is called even if VaryByCustom
// returns a duplicate response!
var culture = requestContext.RouteData.Values["culture"].ToString();
var ci = new CultureInfo(culture);
Thread.CurrentThread.CurrentUICulture = ci;
Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture(ci.Name);
requestContext.HttpContext.RewritePath("~/" + _virtualPath, true);
return _innerServiceRoute.RouteHandler.GetHttpHandler(requestContext);
}
}
最後,服務本身的相關部分:
[ServiceContract]
[AspNetCompatibilityRequirements(
RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class DeviceService
{
[AspNetCacheProfile("MyCacheProfile")]
[WebGet(UriTemplate = "")]
public IEnumerable<DeviceListItemModel> GetDevices()
{
// This is called AFTER the first VaryByCustom override is called.
// I'd expect it not to be called unless VaryByCustom changes!
var devices =
from d in _deviceRepository.GetAll()
where d.ReleaseDate < DateTime.Now
orderby d.Id descending
select new DeviceListItemModel(d);
return devices;
}
UPDATE:我的緩存配置文件:
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="MyCacheProfile" varyByCustom="XmlDataFreshness"
varyByHeader="accept" varyByParam="*" location="Server"
duration="3600" />
</outputCacheProfiles>
</outputCacheSettings>
</caching>
緩存配置文件似乎對我很好,我將它添加到問題的底部以防萬一。 VaryByCustom每次肯定會返回相同的響應。 – roufamatic 2011-06-01 08:22:16
就像測試一樣,你可以去掉varyByHeader =「accept」varyByParam =「*」設置嗎?所以只有varyByCustom仍然存在? – maartenba 2011-06-01 12:16:47
我刪除varyByHeader,但無法刪除varyByParam(拋出一個異常),所以我只是把它留空。不用找了。 Hrmmm。與您的情況相比,我的情況非常簡單,所以我將嘗試使用BeginRequest和RewritePath更簡單的方法。 – roufamatic 2011-06-01 16:09:22