[{"data":1,"prerenderedAt":1008},["ShallowReactive",2],{"blog:2011:behind-the-scenes-at-xbox-com-rss-enabling-web-marketplace":3,"blogMore-Development":994,"comments-behind-the-scenes-at-xbox-com-rss-enabling-web-marketplace":1007},{"id":4,"title":5,"body":6,"category":976,"commentCount":264,"date":977,"description":12,"excerpt":978,"extension":979,"filenames":980,"hidden":981,"image":980,"meta":982,"minutes":249,"navigation":260,"path":983,"seo":984,"showCategory":980,"stem":985,"tags":986,"updated":980,"url":991,"wordCount":992,"__hash__":993},"content\u002Fblog\u002F2011\u002Fbehind-the-scenes-at-xbox-com-rss-enabling-web-marketplace.md","Behind the scenes at xbox.com: RSS enabling web marketplace",{"type":7,"value":8,"toc":970},"minimark",[9,13,16,35,38,41,50,58,63,72,75,97,103,109,112,115,122,564,567,619,795,809,813,816,819,822,946,953,960,966],[10,11,12],"p",{},"A number of people were requesting additional RSS feeds for the xbox.com web marketplace. (We had just one that included all new arrivals)",[10,14,15],{},"Looking across our site as the various lists of products we display today the significant views are:",[17,18,19,23,26,29,32],"ul",{},[20,21,22],"li",{},"Browse games by department",[20,24,25],{},"Search results",[20,27,28],{},"Promotions (e.g. Deal of the week)",[20,30,31],{},"Game detail (shows downloads available beneath it)",[20,33,34],{},"Avatar item browse",[10,36,37],{},"These views also have sorting options and a set of filters available for things like product type, game genre, content rating etc.",[10,39,40],{},"So we had a couple of options:",[42,43,44,47],"ol",{},[20,45,46],{},"Write controller actions that expose the results of specific queries as RSS",[20,48,49],{},"Introduce a mechanism whereby any of our product result pages can render as RSS including any user-defined filtering",[10,51,52,53,57],{},"Our web marketplace is written in ASP.NET MVC (like most of xbox.com) so while option 1 sounds simpler MVC really helps us make option 2 more attractive by way of a useful feature called ",[54,55,56],"code",{},"ActionFilter","s that let us jump in and reshape the way existing actions behave.",[59,60,62],"h2",{"id":61},"actionfilters","ActionFilters",[10,64,65,71],{},[66,67,62],"a",{"href":68,"rel":69},"https:\u002F\u002Fmsdn.microsoft.com\u002Fen-us\u002Flibrary\u002Fgg416513%28VS.98%29.aspx",[70],"nofollow"," can be applied to either to an individual action method on a controller or to the controller class itself which applies it to all the actions on that controller. They provide hooks into the processing pipeline where you can jump in and perform additional processing.",[10,73,74],{},"The most interesting events are:",[17,76,77,82,87,92],{},[20,78,79],{},[54,80,81],{},"OnActionExecuting",[20,83,84],{},[54,85,86],{},"OnActionExecuted",[20,88,89],{},[54,90,91],{},"OnResultExecuting",[20,93,94],{},[54,95,96],{},"OnResultExecuted",[10,98,99,100,102],{},"We’re going to hook in to the ",[54,101,86],{}," step because we always want to run after the code in the controller action has executed but before the ActionResult has done it’s work, i.e. before page or RSS rendering.",[59,104,106,107],{"id":105},"writing-our-actionfilter","Writing our ",[54,108,56],{},[10,110,111],{},"The first thing we want to do is identify that a request wants the RSS version. One way is to read the accepts header and switch when it requests mime\u002Ftype but this can be a little trickier to test,  another is to append a query parameter on the url which is very easy to test.",[10,113,114],{},"Once we’ve identified the incoming request should be for RSS we need to identify the data we want to turn into RSS and re-purpose it.",[10,116,117,118,121],{},"All the views we identified at the start of this post share a common rendering mechanism and each view model sub-classes from one of our base models. For simplicity though we’ll imagine an interface that just exposes an ",[54,119,120],{},"IEnumerable\u003CProduct>"," property.",[123,124,129],"pre",{"className":125,"code":126,"language":127,"meta":128,"style":128},"language-csharp shiki shiki-themes everforest-light dracula","public class RssEnabledAttribute : ActionFilterAttribute {\n  public override void OnActionExecuted(ActionExecutedContext filterContext) {\n    var viewModel = filterContext.Controller.ViewData.Model as IProductResultViewModel;\n    if (viewModel == null)\n        return;\n\n    var rssFeedTitle = FeedHelper.MakeTitle(viewModel.Results);\n    filterContext.Controller.ViewData.Add(\"RssFeedTitle\", rssFeedTitle);\n\n    var format = filterContext.RequestContext.HttpContext.Request.QueryString[\"format\"];\n    if (format == \"rss\" && rssFeedTitle != null) {\n      var urlHelper = new UrlHelper(filterContext.RequestContext);\n      var url = QueryStringUtility.RemoveQueryStringParameter(filterContext.RequestContext.HttpContext.Request.Url.ToString(), \"format\");\n      var feedItems = FeedHelper.GetSyndicationItems(viewModel.Results, urlHelper);\n      filterContext.Result = FeedHelper.CreateProductFeed(rssFeedTitle, viewModel.Description, new Uri(url), feedItems);\n    }\n\n    base.OnActionExecuted(filterContext);\n  }\n}\n","csharp","",[54,130,131,159,189,228,247,255,262,287,319,324,367,397,421,470,492,527,533,538,552,558],{"__ignoreMap":128},[132,133,136,140,144,148,152,156],"span",{"class":134,"line":135},"line",1,[132,137,139],{"class":138},"s9HRq","public",[132,141,143],{"class":142},"smiwp"," class",[132,145,147],{"class":146},"sPLAf"," RssEnabledAttribute",[132,149,151],{"class":150},"s6Vpi"," : ",[132,153,155],{"class":154},"snuxY","ActionFilterAttribute",[132,157,158],{"class":150}," {\n",[132,160,162,165,168,172,176,179,182,186],{"class":134,"line":161},2,[132,163,164],{"class":138},"  public",[132,166,167],{"class":138}," override",[132,169,171],{"class":170},"sXAHl"," void",[132,173,175],{"class":174},"sS4Kt"," OnActionExecuted",[132,177,178],{"class":150},"(",[132,180,181],{"class":154},"ActionExecutedContext",[132,183,185],{"class":184},"s7cAX"," filterContext",[132,187,188],{"class":150},") {\n",[132,190,192,195,198,201,204,208,211,214,216,219,222,225],{"class":134,"line":191},3,[132,193,194],{"class":170},"    var",[132,196,197],{"class":150}," viewModel ",[132,199,200],{"class":138},"=",[132,202,203],{"class":150}," filterContext.",[132,205,207],{"class":206},"sSKRk","Controller",[132,209,210],{"class":150},".",[132,212,213],{"class":206},"ViewData",[132,215,210],{"class":150},[132,217,218],{"class":206},"Model",[132,220,221],{"class":142}," as",[132,223,224],{"class":154}," IProductResultViewModel",[132,226,227],{"class":150},";\n",[132,229,231,234,237,240,244],{"class":134,"line":230},4,[132,232,233],{"class":142},"    if",[132,235,236],{"class":150}," (viewModel ",[132,238,239],{"class":138},"==",[132,241,243],{"class":242},"s3Ipq"," null",[132,245,246],{"class":150},")\n",[132,248,250,253],{"class":134,"line":249},5,[132,251,252],{"class":142},"        return",[132,254,227],{"class":150},[132,256,258],{"class":134,"line":257},6,[132,259,261],{"emptyLinePlaceholder":260},true,"\n",[132,263,265,267,270,272,275,278,281,284],{"class":134,"line":264},7,[132,266,194],{"class":170},[132,268,269],{"class":150}," rssFeedTitle ",[132,271,200],{"class":138},[132,273,274],{"class":150}," FeedHelper.",[132,276,277],{"class":174},"MakeTitle",[132,279,280],{"class":150},"(viewModel.",[132,282,283],{"class":206},"Results",[132,285,286],{"class":150},");\n",[132,288,290,293,295,297,299,301,304,306,310,314,316],{"class":134,"line":289},8,[132,291,292],{"class":150},"    filterContext.",[132,294,207],{"class":206},[132,296,210],{"class":150},[132,298,213],{"class":206},[132,300,210],{"class":150},[132,302,303],{"class":174},"Add",[132,305,178],{"class":150},[132,307,309],{"class":308},"sciFF","\"",[132,311,313],{"class":312},"sJQOs","RssFeedTitle",[132,315,309],{"class":308},[132,317,318],{"class":150},", rssFeedTitle);\n",[132,320,322],{"class":134,"line":321},9,[132,323,261],{"emptyLinePlaceholder":260},[132,325,327,329,332,334,336,339,341,344,346,349,351,354,357,359,362,364],{"class":134,"line":326},10,[132,328,194],{"class":170},[132,330,331],{"class":150}," format ",[132,333,200],{"class":138},[132,335,203],{"class":150},[132,337,338],{"class":206},"RequestContext",[132,340,210],{"class":150},[132,342,343],{"class":206},"HttpContext",[132,345,210],{"class":150},[132,347,348],{"class":206},"Request",[132,350,210],{"class":150},[132,352,353],{"class":206},"QueryString",[132,355,356],{"class":150},"[",[132,358,309],{"class":308},[132,360,361],{"class":312},"format",[132,363,309],{"class":308},[132,365,366],{"class":150},"];\n",[132,368,370,372,375,377,380,383,385,388,390,393,395],{"class":134,"line":369},11,[132,371,233],{"class":142},[132,373,374],{"class":150}," (format ",[132,376,239],{"class":138},[132,378,379],{"class":308}," \"",[132,381,382],{"class":312},"rss",[132,384,309],{"class":308},[132,386,387],{"class":138}," &&",[132,389,269],{"class":150},[132,391,392],{"class":138},"!=",[132,394,243],{"class":242},[132,396,188],{"class":150},[132,398,400,403,406,408,411,414,417,419],{"class":134,"line":399},12,[132,401,402],{"class":170},"      var",[132,404,405],{"class":150}," urlHelper ",[132,407,200],{"class":138},[132,409,410],{"class":142}," new",[132,412,413],{"class":154}," UrlHelper",[132,415,416],{"class":150},"(filterContext.",[132,418,338],{"class":206},[132,420,286],{"class":150},[132,422,424,426,429,431,434,437,439,441,443,445,447,449,451,454,456,459,462,464,466,468],{"class":134,"line":423},13,[132,425,402],{"class":170},[132,427,428],{"class":150}," url ",[132,430,200],{"class":138},[132,432,433],{"class":150}," QueryStringUtility.",[132,435,436],{"class":174},"RemoveQueryStringParameter",[132,438,416],{"class":150},[132,440,338],{"class":206},[132,442,210],{"class":150},[132,444,343],{"class":206},[132,446,210],{"class":150},[132,448,348],{"class":206},[132,450,210],{"class":150},[132,452,453],{"class":206},"Url",[132,455,210],{"class":150},[132,457,458],{"class":174},"ToString",[132,460,461],{"class":150},"(), ",[132,463,309],{"class":308},[132,465,361],{"class":312},[132,467,309],{"class":308},[132,469,286],{"class":150},[132,471,473,475,478,480,482,485,487,489],{"class":134,"line":472},14,[132,474,402],{"class":170},[132,476,477],{"class":150}," feedItems ",[132,479,200],{"class":138},[132,481,274],{"class":150},[132,483,484],{"class":174},"GetSyndicationItems",[132,486,280],{"class":150},[132,488,283],{"class":206},[132,490,491],{"class":150},", urlHelper);\n",[132,493,495,498,501,504,506,509,512,515,518,521,524],{"class":134,"line":494},15,[132,496,497],{"class":150},"      filterContext.",[132,499,500],{"class":206},"Result",[132,502,503],{"class":138}," =",[132,505,274],{"class":150},[132,507,508],{"class":174},"CreateProductFeed",[132,510,511],{"class":150},"(rssFeedTitle, viewModel.",[132,513,514],{"class":206},"Description",[132,516,517],{"class":150},", ",[132,519,520],{"class":142},"new",[132,522,523],{"class":154}," Uri",[132,525,526],{"class":150},"(url), feedItems);\n",[132,528,530],{"class":134,"line":529},16,[132,531,532],{"class":150},"    }\n",[132,534,536],{"class":134,"line":535},17,[132,537,261],{"emptyLinePlaceholder":260},[132,539,541,545,547,549],{"class":134,"line":540},18,[132,542,544],{"class":543},"stJs5","    base",[132,546,210],{"class":150},[132,548,86],{"class":174},[132,550,551],{"class":150},"(filterContext);\n",[132,553,555],{"class":134,"line":554},19,[132,556,557],{"class":150},"  }\n",[132,559,561],{"class":134,"line":560},20,[132,562,563],{"class":150},"}\n",[10,565,566],{},"This class relies on our FeedHelper class to achieve three things it needs:",[42,568,569,574,598],{},[20,570,571,573],{},[54,572,277],{}," takes the request details, i.e. which page, type of products, filtering and sorting is selected and makes a title by re-using our breadcrumbs",[20,575,576,578,579,581,582,585,586,589,590,593,594,597],{},[54,577,484],{}," takes the ",[54,580,120],{}," and turns it into ",[54,583,584],{},"IEnumerable\u003CSyndicationItem>"," by way of a ",[54,587,588],{},"foreach"," projecting ",[54,591,592],{},"Product"," into ",[54,595,596],{},"SyndicationItem"," with some basic HTML formatting, combining the product image and setting the correct category (with a yield thrown in for good measure)",[20,599,600,602,603,606,607,612,613,618],{},[54,601,508],{}," then creates a ",[54,604,605],{},"Syndication"," feed with the appropriate Copyright and Language set and chooses the formatter, in our case ",[66,608,611],{"href":609,"rel":610},"https:\u002F\u002Fmsdn.microsoft.com\u002Fen-us\u002Flibrary\u002Fsystem.servicemodel.syndication.rss20feedformatter.aspx",[70],"RSS 2.0"," but could easily be ",[66,614,617],{"href":615,"rel":616},"https:\u002F\u002Fmsdn.microsoft.com\u002Fen-us\u002Flibrary\u002Fsystem.servicemodel.syndication.atom10feedformatter.aspx",[70],"Atom 1.0",", e.g.",[123,620,622],{"className":125,"code":621,"language":127,"meta":128,"style":128},"public static SyndicationFeedResult CreateProductFeed(string title, string description, Uri link, IEnumerable\u003CSyndicationItem> syndicationItems)\n{\n    var feed = new SyndicationFeed(title, description, link, syndicationItems) {\n        Copyright = new TextSyndicationContent(String.Format(Resources.FeedCopyrightFormat, DateTime.Now.Year)),\n        Language = CultureInfo.CurrentUICulture.Name\n    };\n\n    return new FeedResult(new Rss20FeedFormatter(feed, false));\n}\n",[54,623,624,678,683,700,738,756,761,765,791],{"__ignoreMap":128},[132,625,626,628,631,634,637,639,642,645,647,649,652,654,657,660,662,665,668,670,673,676],{"class":134,"line":135},[132,627,139],{"class":138},[132,629,630],{"class":138}," static",[132,632,633],{"class":154}," SyndicationFeedResult",[132,635,636],{"class":174}," CreateProductFeed",[132,638,178],{"class":150},[132,640,641],{"class":170},"string",[132,643,644],{"class":184}," title",[132,646,517],{"class":150},[132,648,641],{"class":170},[132,650,651],{"class":184}," description",[132,653,517],{"class":150},[132,655,656],{"class":154},"Uri",[132,658,659],{"class":184}," link",[132,661,517],{"class":150},[132,663,664],{"class":154},"IEnumerable",[132,666,667],{"class":150},"\u003C",[132,669,596],{"class":154},[132,671,672],{"class":150},"> ",[132,674,675],{"class":184},"syndicationItems",[132,677,246],{"class":150},[132,679,680],{"class":134,"line":161},[132,681,682],{"class":150},"{\n",[132,684,685,687,690,692,694,697],{"class":134,"line":191},[132,686,194],{"class":170},[132,688,689],{"class":150}," feed ",[132,691,200],{"class":138},[132,693,410],{"class":142},[132,695,696],{"class":154}," SyndicationFeed",[132,698,699],{"class":150},"(title, description, link, syndicationItems) {\n",[132,701,702,705,707,709,712,715,718,721,724,727,730,732,735],{"class":134,"line":230},[132,703,704],{"class":150},"        Copyright ",[132,706,200],{"class":138},[132,708,410],{"class":142},[132,710,711],{"class":154}," TextSyndicationContent",[132,713,714],{"class":150},"(String.",[132,716,717],{"class":174},"Format",[132,719,720],{"class":150},"(Resources.",[132,722,723],{"class":206},"FeedCopyrightFormat",[132,725,726],{"class":150},", DateTime.",[132,728,729],{"class":206},"Now",[132,731,210],{"class":150},[132,733,734],{"class":206},"Year",[132,736,737],{"class":150},")),\n",[132,739,740,743,745,748,751,753],{"class":134,"line":249},[132,741,742],{"class":150},"        Language ",[132,744,200],{"class":138},[132,746,747],{"class":150}," CultureInfo.",[132,749,750],{"class":206},"CurrentUICulture",[132,752,210],{"class":150},[132,754,755],{"class":206},"Name\n",[132,757,758],{"class":134,"line":257},[132,759,760],{"class":150},"    };\n",[132,762,763],{"class":134,"line":264},[132,764,261],{"emptyLinePlaceholder":260},[132,766,767,770,772,775,777,779,782,785,788],{"class":134,"line":289},[132,768,769],{"class":142},"    return",[132,771,410],{"class":142},[132,773,774],{"class":154}," FeedResult",[132,776,178],{"class":150},[132,778,520],{"class":142},[132,780,781],{"class":154}," Rss20FeedFormatter",[132,783,784],{"class":150},"(feed, ",[132,786,787],{"class":242},"false",[132,789,790],{"class":150},"));\n",[132,792,793],{"class":134,"line":321},[132,794,563],{"class":150},[10,796,797,798,804,805,808],{},"The ",[66,799,801],{"href":800},"\u002Fblog\u002F2010\u002Fcreating-rss-feeds-in-asp-net-mvc\u002F",[54,802,803],{},"FeedResult"," class is a simple one that takes the built-in .NET ",[54,806,807],{},"SyndicationFeed"," class and wires it up to MVC by implementing an ActionResult that writes the XML of the SyndicationFeedFormatter into the response as well as setting the application\u002Frss+xml content type and encoding.",[59,810,812],{"id":811},"advertising-the-feed-in-the-head","Advertising the feed in the head",[10,814,815],{},"Now that we have the ability to serve up RSS we need to let browsers know it exists.",[10,817,818],{},"The ActionFilter we wrote above needs to know the title of the RSS feed regardless of whether it is rendering the RSS (which needs a title) or rendering the page (which will need to advertise the RSS title) so it always calculates it and then puts it into the ViewData dictionary with the key RssFeedTitle.",[10,820,821],{},"Now finally our site’s master page can check for the existence of that key\u002Fvalue pair and advertise it out with a simple link tag:",[123,823,825],{"className":125,"code":824,"language":127,"meta":128,"style":128},"var rssFeedTitle = ViewData[\"RssFeedTitle\"] as string;\nif (!String.IsNullOrEmpty(rssFeedTitle)) { %>\n\u003Clink rel=\"alternate\" type=\"application\u002Frss+xml\" title=\"\u003C%:rssFeedTitle%>\" href=\"\u003C%:Url.ForThisAsRssFeed%>\" \u002F>\n\u003C% }\n",[54,826,827,858,881,938],{"__ignoreMap":128},[132,828,829,832,834,836,839,841,843,845,847,850,853,856],{"class":134,"line":135},[132,830,831],{"class":170},"var",[132,833,269],{"class":150},[132,835,200],{"class":138},[132,837,838],{"class":206}," ViewData",[132,840,356],{"class":150},[132,842,309],{"class":308},[132,844,313],{"class":312},[132,846,309],{"class":308},[132,848,849],{"class":150},"] ",[132,851,852],{"class":142},"as",[132,854,855],{"class":170}," string",[132,857,227],{"class":150},[132,859,860,863,866,869,872,875,878],{"class":134,"line":161},[132,861,862],{"class":142},"if",[132,864,865],{"class":150}," (",[132,867,868],{"class":138},"!",[132,870,871],{"class":150},"String.",[132,873,874],{"class":174},"IsNullOrEmpty",[132,876,877],{"class":150},"(rssFeedTitle)) { ",[132,879,880],{"class":138},"%>\n",[132,882,883,885,888,891,893,895,898,900,903,905,907,910,912,914,916,918,921,923,926,928,930,933,935],{"class":134,"line":191},[132,884,667],{"class":138},[132,886,887],{"class":154},"link",[132,889,890],{"class":150}," rel",[132,892,200],{"class":138},[132,894,309],{"class":308},[132,896,897],{"class":312},"alternate",[132,899,309],{"class":308},[132,901,902],{"class":150}," type",[132,904,200],{"class":138},[132,906,309],{"class":308},[132,908,909],{"class":312},"application\u002Frss+xml",[132,911,309],{"class":308},[132,913,644],{"class":150},[132,915,200],{"class":138},[132,917,309],{"class":308},[132,919,920],{"class":312},"\u003C%:rssFeedTitle%>",[132,922,309],{"class":308},[132,924,925],{"class":150}," href",[132,927,200],{"class":138},[132,929,309],{"class":308},[132,931,932],{"class":312},"\u003C%:Url.ForThisAsRssFeed%>",[132,934,309],{"class":308},[132,936,937],{"class":138}," \u002F>\n",[132,939,940,943],{"class":134,"line":230},[132,941,942],{"class":138},"\u003C%",[132,944,945],{"class":150}," }\n",[10,947,948,949,952],{},"This code requires just one more thing, a very small UrlHelper which will append ",[54,950,951],{},"format=rss"," to the query string (taking into account whether there existing query parameters or not).",[10,954,955,956,959],{},"The result of this is we can now just add ",[54,957,958],{},"[RssEnabled]"," in front of any controller or action to turn on RSS feeds for that portion of our marketplace! :)",[10,961,962],{},[963,964,965],"em",{},"[)amien",[967,968,969],"style",{},"html pre.shiki code .s9HRq, html code.shiki .s9HRq{--shiki-default:#F57D26;--shiki-dark:#FF79C6}html pre.shiki code .smiwp, html code.shiki .smiwp{--shiki-default:#F85552;--shiki-dark:#FF79C6}html pre.shiki code .sPLAf, html code.shiki .sPLAf{--shiki-default:#3A94C5;--shiki-dark:#8BE9FD}html pre.shiki code .s6Vpi, html code.shiki .s6Vpi{--shiki-default:#5C6A72;--shiki-dark:#F8F8F2}html pre.shiki code .snuxY, html code.shiki .snuxY{--shiki-default:#3A94C5;--shiki-default-font-style:inherit;--shiki-dark:#8BE9FD;--shiki-dark-font-style:italic}html pre.shiki code .sXAHl, html code.shiki .sXAHl{--shiki-default:#3A94C5;--shiki-dark:#FF79C6}html pre.shiki code .sS4Kt, html code.shiki .sS4Kt{--shiki-default:#8DA101;--shiki-dark:#50FA7B}html pre.shiki code .s7cAX, html code.shiki .s7cAX{--shiki-default:#5C6A72;--shiki-default-font-style:inherit;--shiki-dark:#FFB86C;--shiki-dark-font-style:italic}html pre.shiki code .sSKRk, html code.shiki .sSKRk{--shiki-default:#35A77C;--shiki-dark:#F8F8F2}html pre.shiki code .s3Ipq, html code.shiki .s3Ipq{--shiki-default:#DF69BA;--shiki-dark:#BD93F9}html pre.shiki code .sciFF, html code.shiki .sciFF{--shiki-default:#8DA101;--shiki-dark:#E9F284}html pre.shiki code .sJQOs, html code.shiki .sJQOs{--shiki-default:#8DA101;--shiki-dark:#F1FA8C}html pre.shiki code .stJs5, html code.shiki .stJs5{--shiki-default:#5C6A72;--shiki-default-font-style:inherit;--shiki-dark:#BD93F9;--shiki-dark-font-style:italic}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":128,"searchDepth":161,"depth":161,"links":971},[972,973,975],{"id":61,"depth":161,"text":62},{"id":105,"depth":161,"text":974},"Writing our ActionFilter",{"id":811,"depth":161,"text":812},"Development","2011-07-07T12:05:44+00:00","[object Object]","md",null,false,{},"\u002Fblog\u002F2011\u002Fbehind-the-scenes-at-xbox-com-rss-enabling-web-marketplace",{"title":5,"description":12},"blog\u002F2011\u002Fbehind-the-scenes-at-xbox-com-rss-enabling-web-marketplace",[987,988,989,990],".NET","ASP.NET","RSS","Xbox","\u002Fblog\u002F2011\u002Fbehind-the-scenes-at-xbox-com-rss-enabling-web-marketplace\u002F",1059,"mbh1NdGMRxmldhGk5lXDYqL5ObkhQFUlOHw_TJrcLnQ",[995,999,1003],{"title":996,"date":997,"url":998},"Transactions in the MongoDB EF Core Provider","2025-10-25","\u002Fblog\u002F2025\u002Fmongodb-explicit-transactions\u002F",{"title":1000,"date":1001,"url":1002},"Queryable Encryption with the MongoDB EF Core Provider","2025-09-22","\u002Fblog\u002F2025\u002Fmongodb-queryable-encryption\u002F",{"title":1004,"date":1005,"url":1006},"Lazy Loading with EF Core Proxies","2025-04-02","\u002Fblog\u002F2025\u002Fef-proxies\u002F",[],1780900526859]