public class PartialViewRenderer : IPartialViewRenderer { public string Render(Controller controller,string viewName,object model) { if (string.IsNullOrEmpty(viewName)) viewName = controller.ControllerContext.RouteData.GetrequiredString("action"); controller.ViewData.Model = model; using (StringWriter sw = new StringWriter()) { ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext,viewName); ViewContext viewContext = new ViewContext(controller.ControllerContext,viewResult.View,controller.ViewData,controller.TempData,sw); viewResult.View.Render(viewContext,sw); return sw.GetStringBuilder().ToString(); } } }
当我第一次将我的应用程序转换为MVC 4时,遇到问题,它正在得到运行时异常.所以我尝试修复需要修复的内容,这使我改变了Hanselmans MockHelpers上的以下方法:(我基本上改变了HttpContext.Items,因为它被吹出了一个“null”的异常)
public static HttpContextBase FakeHttpContext() { var context = new Mock<HttpContextBase>(); var request = new Mock<HttpRequestBase>(); var response = new Mock<HttpResponseBase>(); var session = new Mock<HttpSessionStateBase>(); var server = new Mock<HttpServerUtilityBase>(); var cookies = new HttpCookieCollection(); var items = new ListDictionary(); request.Setup(r => r.Cookies).Returns(cookies); response.Setup(r => r.Cookies).Returns(cookies); context.Setup(ctx => ctx.Items).Returns(items); context.SetupGet(ctx => ctx.Request).Returns(request.Object); context.SetupGet(ctx => ctx.Response).Returns(response.Object); context.SetupGet(ctx => ctx.Session).Returns(session.Object); context.SetupGet(ctx => ctx.Server).Returns(server.Object); return context.Object; } public static void SetFakeControllerContext(this Controller controller,RouteData route) { var httpContext = FakeHttpContext(); ControllerContext context = new ControllerContext(new RequestContext(httpContext,route),controller); controller.ControllerContext = context; }
这里有一个非常简单的nUnit测试,我必须尝试并确定我需要做什么改变,这个模拟的http上下文(我甚至没有说出来)
[Test] public void test() { _contactsController = _container.Resolve<ContactsController>(); var route = new RouteData(); route.Values.Add("controller","ContactsController"); route.Values.Add("action","GetEditContactDetailsDialog"); _contactsController.SetFakeControllerContext(route); var result = _contactsController.GetEditContactDetailsDialog("1"); }
现在当我运行这个测试它在PartialViewRenderer.Render调用onEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext,viewName);这是以下堆栈跟踪.
at System.Web.WebPages.DisplayModeProvider.<.ctor>b__2(HttpContextBase context)
at System.Web.WebPages.DefaultDisplayMode.CanHandleContext(HttpContextBase httpContext)
at System.Web.WebPages.DisplayModeProvider.<>c__DisplayClass6.b__5(IDisplayMode mode)
at System.Linq.Enumerable.WhereListIterator1.MoveNext()
1..ctor(IEnumerable
at System.Collections.Generic.List1 collection)
1 source)
at System.Linq.Enumerable.ToList[TSource](IEnumerable
at System.Web.WebPages.DisplayModeProvider.GetAvailableDisplayModesForContext(HttpContextBase httpContext,IDisplayMode currentDisplayMode)
at System.Web.Mvc.VirtualPathProviderViewEngine.GetPath(ControllerContext controllerContext,String[] locations,String[] areaLocations,String locationsPropertyName,String name,String controllerName,String cacheKeyPrefix,Boolean useCache,String[]& searchedLocations)
解决方法
var context = new Mock<HttpContextBase>(MockBehavior.Strict);
使用它可以找到与DisplayMode的依赖关系.
二,DisplayMode是asp.net mvc中的新功能4:
http://www.asp.net/whitepapers/mvc4-release-notes#_Toc303253810
所以,它得到Request.Browser参数,以确定使用哪个View.添加Mock浏览器:
var browser = new Mock<HttpBrowserCapabilitiesBase>(MockBehavior.Strict); var context = new Mock<HttpContextBase>(MockBehavior.Strict); var request = new Mock<HttpRequestBase>(MockBehavior.Strict); var response = new Mock<HttpResponseBase>(MockBehavior.Strict); var session = new Mock<HttpSessionStateBase>(MockBehavior.Strict); var server = new Mock<HttpServerUtilityBase>(MockBehavior.Strict); var cookies = new HttpCookieCollection(); var items = new ListDictionary(); browser.Setup(b => b.IsMobileDevice).Returns(false); request.Setup(r => r.Cookies).Returns(cookies); request.Setup(r => r.ValidateInput()); request.Setup(r => r.UserAgent).Returns("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML,like Gecko) Chrome/23.0.1271.64 Safari/537.11"); response.Setup(r => r.Cookies).Returns(cookies); request.Setup(r => r.Browser).Returns(browser.Object); context.Setup(ctx => ctx.Items).Returns(items);