Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

Commit

Permalink
* Allow null ViewData and TempData
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanbrandenburg committed Oct 23, 2015
1 parent 911dfc5 commit 0b8fe87
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 18 deletions.
12 changes: 9 additions & 3 deletions src/Microsoft.AspNet.Mvc.ViewFeatures/ViewComponentResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ public override async Task ExecuteResultAsync(ActionContext context)
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)
{
Expand All @@ -98,8 +104,8 @@ public override async Task ExecuteResultAsync(ActionContext context)
// 3. ViewExecutor.DefaultContentType (sensible default)
//
//
response.ContentType =
contentType?.ToString() ??
response.ContentType =
contentType?.ToString() ??
response.ContentType ??
ViewExecutor.DefaultContentType.ToString();

Expand All @@ -115,7 +121,7 @@ public override async Task ExecuteResultAsync(ActionContext context)
context,
NullView.Instance,
viewData,
TempData,
tempData,
writer,
htmlHelperOptions);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
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;

Expand Down Expand Up @@ -117,14 +119,16 @@ public virtual async Task ExecuteAsync(
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,32 @@ public class ViewComponentResultTest
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()
{
Expand Down Expand Up @@ -76,10 +102,10 @@ public async Task ExecuteResultAsync_Throws_IfViewComponentCouldNotBeFound_ByTyp
// 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
{
Expand Down Expand Up @@ -387,8 +413,11 @@ public async Task ViewComponentResult_NoContentTypeSet_PreservesResponseContentT
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>();
Expand All @@ -400,15 +429,17 @@ private IServiceCollection CreateServices(params ViewComponentDescriptor[] descr
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();

Expand Down Expand Up @@ -467,4 +498,4 @@ private static string ReadBody(HttpResponse response)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,11 @@ public void ObjectTemplateDisplaysSimpleDisplayTextWhenTemplateDepthGreaterThanO
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>()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
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;
Expand Down Expand Up @@ -112,6 +114,62 @@ await viewExecutor.ExecuteAsync(
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()
{
Expand Down

0 comments on commit 0b8fe87

Please sign in to comment.