* Allow null ViewData and TempData

This commit is contained in:
ryanbrandenburg 2015-10-12 12:32:50 -07:00
parent 911dfc57b0
commit 0b8fe87596
5 changed files with 116 additions and 18 deletions

View File

@ -84,6 +84,12 @@ namespace Microsoft.AspNet.Mvc
viewData = new ViewDataDictionary(modelMetadataProvider, context.ModelState);
}
var tempData = TempData;
if (tempData == null)
{
tempData = services.GetRequiredService<ITempDataDictionary>();
}
var contentType = ContentType;
if (contentType != null && contentType.Encoding == null)
{
@ -98,8 +104,8 @@ namespace Microsoft.AspNet.Mvc
// 3. ViewExecutor.DefaultContentType (sensible default)
//
//
response.ContentType =
contentType?.ToString() ??
response.ContentType =
contentType?.ToString() ??
response.ContentType ??
ViewExecutor.DefaultContentType.ToString();
@ -115,7 +121,7 @@ namespace Microsoft.AspNet.Mvc
context,
NullView.Instance,
viewData,
TempData,
tempData,
writer,
htmlHelperOptions);

View File

@ -6,8 +6,10 @@ using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Infrastructure;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.ViewEngines;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.OptionsModel;
using Microsoft.Net.Http.Headers;
@ -117,14 +119,16 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
throw new ArgumentNullException(nameof(view));
}
var services = actionContext.HttpContext.RequestServices;
if (viewData == null)
{
throw new ArgumentNullException(nameof(viewData));
var metadataProvider = services.GetRequiredService<IModelMetadataProvider>();
viewData = new ViewDataDictionary(metadataProvider);
}
if (tempData == null)
{
throw new ArgumentNullException(nameof(tempData));
tempData = services.GetRequiredService<ITempDataDictionary>();
}
var response = actionContext.HttpContext.Response;

View File

@ -29,6 +29,32 @@ namespace Microsoft.AspNet.Mvc
private readonly ITempDataDictionary _tempDataDictionary =
new TempDataDictionary(new HttpContextAccessor(), new SessionStateTempDataProvider());
[Fact]
public async Task ExecuteAsync_ViewComponentResult_AllowsNullViewDataAndTempData()
{
// Arrange
var descriptor = new ViewComponentDescriptor()
{
FullName = "Full.Name.Text",
ShortName = "Text",
Type = typeof(TextViewComponent),
};
var actionContext = CreateActionContext(descriptor);
var viewComponentResult = new ViewComponentResult
{
Arguments = new object[] { "World!" },
ViewData = null,
TempData = null,
ViewComponentName = "Text"
};
// Act
await viewComponentResult.ExecuteResultAsync(actionContext);
// No assert, just confirm it didn't throw
}
[Fact]
public async Task ExecuteResultAsync_Throws_IfNameOrTypeIsNotSet()
{
@ -76,10 +102,10 @@ namespace Microsoft.AspNet.Mvc
// Arrange
var expected = $"A view component named '{typeof(TextViewComponent).FullName}' could not be found.";
var services = CreateServices();
var actionContext = CreateActionContext();
var services = CreateServices(actionContext.HttpContext);
services.AddSingleton<IViewComponentSelector>();
var actionContext = CreateActionContext();
var viewComponentResult = new ViewComponentResult
{
@ -387,8 +413,11 @@ namespace Microsoft.AspNet.Mvc
Assert.Equal(expectedContentType, actionContext.HttpContext.Response.ContentType);
}
private IServiceCollection CreateServices(params ViewComponentDescriptor[] descriptors)
{
private IServiceCollection CreateServices(HttpContext context, params ViewComponentDescriptor[] descriptors)
{
var httpContext = new HttpContextAccessor() { HttpContext = context };
var tempDataProvider = new SessionStateTempDataProvider();
var services = new ServiceCollection();
services.AddSingleton<IOptions<MvcViewOptions>, TestOptionsManager<MvcViewOptions>>();
services.AddTransient<IViewComponentHelper, DefaultViewComponentHelper>();
@ -400,15 +429,17 @@ namespace Microsoft.AspNet.Mvc
services.AddInstance<IViewComponentDescriptorProvider>(new FixedSetViewComponentDescriptorProvider(descriptors));
services.AddSingleton<IModelMetadataProvider, EmptyModelMetadataProvider>();
services.AddInstance<ILoggerFactory>(NullLoggerFactory.Instance);
services.AddInstance<ITempDataDictionary>(new TempDataDictionary(httpContext, tempDataProvider));
services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();
return services;
}
private HttpContext CreateHttpContext(params ViewComponentDescriptor[] descriptors)
{
var services = CreateServices(descriptors);
var httpContext = new DefaultHttpContext();
var services = CreateServices(httpContext, descriptors);
httpContext.Response.Body = new MemoryStream();
httpContext.RequestServices = services.BuildServiceProvider();
@ -467,4 +498,4 @@ namespace Microsoft.AspNet.Mvc
}
}
}
}
}

View File

@ -122,12 +122,11 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
public void ObjectTemplate_IgnoresPropertiesWith_ScaffoldColumnFalse()
{
// Arrange
var expected =
@"<div class=""HtmlEncode[[display-label]]"">HtmlEncode[[Property1]]</div>
<div class=""HtmlEncode[[display-field]]""></div>
<div class=""HtmlEncode[[display-label]]"">HtmlEncode[[Property3]]</div>
<div class=""HtmlEncode[[display-field]]""></div>
";
var expected = "<div class=\"HtmlEncode[[display-label]]\">HtmlEncode[[Property1]]</div>" + Environment.NewLine +
"<div class=\"HtmlEncode[[display-field]]\"></div>"+ Environment.NewLine +
"<div class=\"HtmlEncode[[display-label]]\">HtmlEncode[[Property3]]</div>"+ Environment.NewLine +
"<div class=\"HtmlEncode[[display-field]]\"></div>"+ Environment.NewLine;
var model = new DefaultTemplatesUtilities.ObjectWithScaffoldColumn();
var viewEngine = new Mock<ICompositeViewEngine>();
viewEngine.Setup(v => v.FindPartialView(It.IsAny<ActionContext>(), It.IsAny<string>()))

View File

@ -8,12 +8,14 @@ using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.Abstractions;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.ViewEngines;
using Microsoft.AspNet.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@ -112,6 +114,62 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
Assert.Equal("abcd", Encoding.UTF8.GetString(memoryStream.ToArray()));
}
private static IServiceProvider GetServiceProvider()
{
var httpContext = new HttpContextAccessor() { HttpContext = new DefaultHttpContext() };
var serviceCollection = new ServiceCollection();
serviceCollection.AddInstance<IModelMetadataProvider>(new EmptyModelMetadataProvider());
var tempDataProvider = new SessionStateTempDataProvider();
serviceCollection.AddInstance<ITempDataDictionary>(new TempDataDictionary(httpContext, tempDataProvider));
return serviceCollection.BuildServiceProvider();
}
[Fact]
public async Task ExecuteAsync_ViewResultAllowNull()
{
// Arrange
var tempDataNull = false;
var viewDataNull = false;
var deligateHit = false;
var view = CreateView(async (v) =>
{
deligateHit = true;
tempDataNull = v.TempData == null;
viewDataNull = v.ViewData == null;
await v.Writer.WriteAsync("abcd");
});
var context = new DefaultHttpContext();
var memoryStream = new MemoryStream();
context.Response.Body = memoryStream;
var actionContext = new ActionContext(
context,
new RouteData(),
new ActionDescriptor());
context.RequestServices = GetServiceProvider();
var viewExecutor = CreateViewExecutor();
// Act
await viewExecutor.ExecuteAsync(
actionContext,
view,
null,
null,
contentType: null,
statusCode: 200);
// Assert
Assert.Equal(200, context.Response.StatusCode);
Assert.True(deligateHit);
Assert.False(viewDataNull);
Assert.False(tempDataNull);
}
[Fact]
public async Task ExecuteAsync_SetsStatusCode()
{