* Allow null ViewData and TempData
This commit is contained in:
parent
911dfc57b0
commit
0b8fe87596
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>()))
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue