Remove ComponentResultHelper

Fix #598
This commit is contained in:
Tian Pan 2014-06-11 11:28:19 -07:00
parent e95585dfbd
commit 31915f0b46
9 changed files with 75 additions and 146 deletions

View File

@ -212,14 +212,12 @@
<Compile Include="ViewComponents\DefaultViewComponentInvoker.cs" /> <Compile Include="ViewComponents\DefaultViewComponentInvoker.cs" />
<Compile Include="ViewComponents\DefaultViewComponentInvokerFactory.cs" /> <Compile Include="ViewComponents\DefaultViewComponentInvokerFactory.cs" />
<Compile Include="ViewComponents\DefaultViewComponentInvokerProvider.cs" /> <Compile Include="ViewComponents\DefaultViewComponentInvokerProvider.cs" />
<Compile Include="ViewComponents\DefaultViewComponentResultHelper.cs" />
<Compile Include="ViewComponents\DefaultViewComponentSelector.cs" /> <Compile Include="ViewComponents\DefaultViewComponentSelector.cs" />
<Compile Include="ViewComponents\IViewComponentHelper.cs" /> <Compile Include="ViewComponents\IViewComponentHelper.cs" />
<Compile Include="ViewComponents\IViewComponentInvoker.cs" /> <Compile Include="ViewComponents\IViewComponentInvoker.cs" />
<Compile Include="ViewComponents\IViewComponentInvokerFactory.cs" /> <Compile Include="ViewComponents\IViewComponentInvokerFactory.cs" />
<Compile Include="ViewComponents\IViewComponentInvokerProvider.cs" /> <Compile Include="ViewComponents\IViewComponentInvokerProvider.cs" />
<Compile Include="ViewComponents\IViewComponentResult.cs" /> <Compile Include="ViewComponents\IViewComponentResult.cs" />
<Compile Include="ViewComponents\IViewComponentResultHelper.cs" />
<Compile Include="ViewComponents\IViewComponentSelector.cs" /> <Compile Include="ViewComponents\IViewComponentSelector.cs" />
<Compile Include="ViewComponents\JsonViewComponentResult.cs" /> <Compile Include="ViewComponents\JsonViewComponentResult.cs" />
<Compile Include="ViewComponents\ViewComponent.cs" /> <Compile Include="ViewComponents\ViewComponent.cs" />

View File

@ -9,26 +9,30 @@ namespace Microsoft.AspNet.Mvc
{ {
public class ContentViewComponentResult : IViewComponentResult public class ContentViewComponentResult : IViewComponentResult
{ {
private readonly HtmlString _encoded;
public ContentViewComponentResult([NotNull] string content) public ContentViewComponentResult([NotNull] string content)
{ {
_encoded = new HtmlString(WebUtility.HtmlEncode(content)); Content = content;
EncodedContent = new HtmlString(WebUtility.HtmlEncode(content));
} }
public ContentViewComponentResult([NotNull] HtmlString encoded) public ContentViewComponentResult([NotNull] HtmlString encodedContent)
{ {
_encoded = encoded; EncodedContent = encodedContent;
Content = WebUtility.HtmlDecode(encodedContent.ToString());
} }
public string Content { get; private set; }
public HtmlString EncodedContent { get; private set; }
public void Execute([NotNull] ViewComponentContext context) public void Execute([NotNull] ViewComponentContext context)
{ {
context.Writer.Write(_encoded.ToString()); context.Writer.Write(EncodedContent.ToString());
} }
public async Task ExecuteAsync([NotNull] ViewComponentContext context) public async Task ExecuteAsync([NotNull] ViewComponentContext context)
{ {
await context.Writer.WriteAsync(_encoded.ToString()); await context.Writer.WriteAsync(EncodedContent.ToString());
} }
} }
} }

View File

@ -1,32 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Mvc.Rendering;
namespace Microsoft.AspNet.Mvc
{
public class DefaultViewComponentResultHelper : IViewComponentResultHelper
{
private readonly IViewEngine _viewEngine;
public DefaultViewComponentResultHelper(IViewEngine viewEngine)
{
_viewEngine = viewEngine;
}
public virtual ContentViewComponentResult Content([NotNull] string content)
{
return new ContentViewComponentResult(content);
}
public virtual JsonViewComponentResult Json([NotNull] object value)
{
return new JsonViewComponentResult(value);
}
public virtual ViewViewComponentResult View([NotNull] string viewName, [NotNull] ViewDataDictionary viewData)
{
return new ViewViewComponentResult(_viewEngine, viewName, viewData);
}
}
}

View File

@ -1,16 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Mvc.Rendering;
namespace Microsoft.AspNet.Mvc
{
public interface IViewComponentResultHelper
{
ContentViewComponentResult Content([NotNull] string content);
JsonViewComponentResult Json([NotNull] object value);
ViewViewComponentResult View([NotNull] string viewName, [NotNull] ViewDataDictionary viewData);
}
}

View File

@ -9,16 +9,16 @@ namespace Microsoft.AspNet.Mvc
{ {
public class JsonViewComponentResult : IViewComponentResult public class JsonViewComponentResult : IViewComponentResult
{ {
private readonly object _value;
private JsonSerializerSettings _jsonSerializerSettings; private JsonSerializerSettings _jsonSerializerSettings;
public JsonViewComponentResult([NotNull] object value) public JsonViewComponentResult([NotNull] object data)
{ {
_value = value; Data = data;
_jsonSerializerSettings = JsonOutputFormatter.CreateDefaultSettings(); _jsonSerializerSettings = JsonOutputFormatter.CreateDefaultSettings();
} }
public object Data { get; private set; }
public JsonSerializerSettings SerializerSettings public JsonSerializerSettings SerializerSettings
{ {
get { return _jsonSerializerSettings; } get { return _jsonSerializerSettings; }
@ -42,7 +42,7 @@ namespace Microsoft.AspNet.Mvc
public void Execute([NotNull] ViewComponentContext context) public void Execute([NotNull] ViewComponentContext context)
{ {
var formatter = new JsonOutputFormatter(SerializerSettings, Indent); var formatter = new JsonOutputFormatter(SerializerSettings, Indent);
formatter.WriteObject(context.Writer, _value); formatter.WriteObject(context.Writer, Data);
} }
#pragma warning disable 1998 #pragma warning disable 1998

View File

@ -10,14 +10,13 @@ namespace Microsoft.AspNet.Mvc
public abstract class ViewComponent public abstract class ViewComponent
{ {
private dynamic _viewBag; private dynamic _viewBag;
private IViewEngine _viewEngine;
public HttpContext Context public HttpContext Context
{ {
get { return ViewContext == null ? null : ViewContext.HttpContext; } get { return ViewContext == null ? null : ViewContext.HttpContext; }
} }
public IViewComponentResultHelper Result { get; private set; }
public dynamic ViewBag public dynamic ViewBag
{ {
get get
@ -35,19 +34,19 @@ namespace Microsoft.AspNet.Mvc
public ViewDataDictionary ViewData { get; set; } public ViewDataDictionary ViewData { get; set; }
public ContentViewComponentResult Content(string content) public ContentViewComponentResult Content([NotNull] string content)
{ {
return Result.Content(content); return new ContentViewComponentResult(content);
} }
public void Initialize(IViewComponentResultHelper result) public void Initialize(IViewEngine viewEngine)
{ {
Result = result; _viewEngine = viewEngine;
} }
public JsonViewComponentResult Json(object value) public JsonViewComponentResult Json([NotNull] object value)
{ {
return Result.Json(value); return new JsonViewComponentResult(value);
} }
public ViewViewComponentResult View() public ViewViewComponentResult View()
@ -73,7 +72,7 @@ namespace Microsoft.AspNet.Mvc
viewData.Model = model; viewData.Model = model;
} }
return Result.View(viewName ?? "Default", viewData); return new ViewViewComponentResult(_viewEngine, viewName, viewData);
} }
} }
} }

View File

@ -14,19 +14,20 @@ namespace Microsoft.AspNet.Mvc
{ {
// {0} is the component name, {1} is the view name. // {0} is the component name, {1} is the view name.
private const string ViewPathFormat = "Components/{0}/{1}"; private const string ViewPathFormat = "Components/{0}/{1}";
private readonly IViewEngine _viewEngine; private readonly IViewEngine _viewEngine;
private readonly string _viewName;
private readonly ViewDataDictionary _viewData;
public ViewViewComponentResult([NotNull] IViewEngine viewEngine, [NotNull] string viewName, public ViewViewComponentResult([NotNull] IViewEngine viewEngine, string viewName,
ViewDataDictionary viewData) ViewDataDictionary viewData)
{ {
_viewEngine = viewEngine; _viewEngine = viewEngine;
_viewName = viewName; ViewName = viewName;
_viewData = viewData; ViewData = viewData;
} }
public string ViewName { get; private set; }
public ViewDataDictionary ViewData { get; private set; }
public void Execute([NotNull] ViewComponentContext context) public void Execute([NotNull] ViewComponentContext context)
{ {
throw new NotImplementedException("There's no support for syncronous views right now."); throw new NotImplementedException("There's no support for syncronous views right now.");
@ -35,10 +36,10 @@ namespace Microsoft.AspNet.Mvc
public async Task ExecuteAsync([NotNull] ViewComponentContext context) public async Task ExecuteAsync([NotNull] ViewComponentContext context)
{ {
string qualifiedViewName; string qualifiedViewName;
if (_viewName.Length > 0 && _viewName[0] == '/') if (ViewName != null && ViewName.Length > 0 && ViewName[0] == '/')
{ {
// View name that was passed in is already a rooted path, the view engine will handle this. // View name that was passed in is already a rooted path, the view engine will handle this.
qualifiedViewName = _viewName; qualifiedViewName = ViewName;
} }
else else
{ {
@ -57,7 +58,7 @@ namespace Microsoft.AspNet.Mvc
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
ViewPathFormat, ViewPathFormat,
ViewComponentConventions.GetComponentName(context.ComponentType), ViewComponentConventions.GetComponentName(context.ComponentType),
_viewName); ViewName ?? "Default");
} }
var view = FindView(context.ViewContext.RouteData.Values, qualifiedViewName); var view = FindView(context.ViewContext.RouteData.Values, qualifiedViewName);
@ -65,7 +66,7 @@ namespace Microsoft.AspNet.Mvc
var childViewContext = new ViewContext( var childViewContext = new ViewContext(
context.ViewContext, context.ViewContext,
view, view,
_viewData ?? context.ViewContext.ViewData, ViewData ?? context.ViewContext.ViewData,
context.Writer); context.Writer);
using (view as IDisposable) using (view as IDisposable)

View File

@ -77,7 +77,6 @@ namespace Microsoft.AspNet.Mvc
yield return describe.Transient<IViewComponentInvokerFactory, DefaultViewComponentInvokerFactory>(); yield return describe.Transient<IViewComponentInvokerFactory, DefaultViewComponentInvokerFactory>();
yield return describe.Transient<INestedProvider<ViewComponentInvokerProviderContext>, yield return describe.Transient<INestedProvider<ViewComponentInvokerProviderContext>,
DefaultViewComponentInvokerProvider>(); DefaultViewComponentInvokerProvider>();
yield return describe.Transient<IViewComponentResultHelper, DefaultViewComponentResultHelper>();
yield return describe.Transient<IViewComponentHelper, DefaultViewComponentHelper>(); yield return describe.Transient<IViewComponentHelper, DefaultViewComponentHelper>();
yield return describe.Transient<IAuthorizationService, DefaultAuthorizationService>(); yield return describe.Transient<IAuthorizationService, DefaultAuthorizationService>();

View File

@ -1,13 +1,9 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic; using System.Net;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Moq;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
@ -53,140 +49,120 @@ namespace Microsoft.AspNet.Mvc
} }
[Fact] [Fact]
public void ViewComponent_Content_CallsResultContentWithTestContent() public void ViewComponent_Content_SetsResultContentAndEncodedContent()
{ {
// Arrange // Arrange
var viewComponent = new TestViewComponent(); var viewComponent = new TestViewComponent();
var resultHelperMock = new Mock<DefaultViewComponentResultHelper>(It.IsAny<IViewEngine>()); var expectedContent = "TestContent&";
var resultMock = new Mock<ContentViewComponentResult>("TestContent"); var expectedEncodedContent = new HtmlString(WebUtility.HtmlEncode(expectedContent));
resultHelperMock.Setup(r => r.Content(It.IsAny<string>()))
.Returns(resultMock.Object);
viewComponent.Initialize(resultHelperMock.Object);
// Act // Act
var actualResult = viewComponent.Content("TestContent"); var actualResult = viewComponent.Content(expectedContent);
// Assert // Assert
resultHelperMock.Verify(r => r.Content("TestContent")); Assert.IsType<ContentViewComponentResult>(actualResult);
Assert.Same(resultMock.Object, actualResult); Assert.Same(expectedContent, actualResult.Content);
Assert.Equal(expectedEncodedContent.ToString(), actualResult.EncodedContent.ToString());
} }
[Fact] [Fact]
public void ViewComponent_Json_CallsResultJsonWithTestValue() public void ViewComponent_Json_SetsResultData()
{ {
// Arrange // Arrange
var viewComponent = new TestViewComponent(); var viewComponent = new TestViewComponent();
var resultHelperMock = new Mock<DefaultViewComponentResultHelper>(It.IsAny<IViewEngine>()); var testData = new object();
var resultMock = new Mock<JsonViewComponentResult>(It.IsAny<object>());
resultHelperMock.Setup(r => r.Json(It.IsAny<object>()))
.Returns(resultMock.Object);
viewComponent.Initialize(resultHelperMock.Object);
var testValue = new object();
// Act // Act
var actualResult = viewComponent.Json(testValue); var actualResult = viewComponent.Json(testData);
// Assert // Assert
resultHelperMock.Verify(r => r.Json(testValue)); Assert.IsType<JsonViewComponentResult>(actualResult);
Assert.Same(resultMock.Object, actualResult); Assert.Same(testData, actualResult.Data);
} }
[Fact] [Fact]
public void ViewComponent_View_WithEmptyParameter_CallsResultViewWithDefaultViewName() public void ViewComponent_View_WithEmptyParameter_SetsResultViewWithDefaultViewName()
{ {
// Arrange // Arrange
var viewComponent = new TestViewComponent() var viewComponent = new TestViewComponent()
{ {
ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider()), ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider()),
}; };
var resultHelperMock = new Mock<DefaultViewComponentResultHelper>(It.IsAny<IViewEngine>());
var resultMock = new Mock<ViewViewComponentResult>(It.IsAny<IViewEngine>(),
It.IsAny<string>(),
It.IsAny<ViewDataDictionary>());
resultHelperMock.Setup(r => r.View(It.IsAny<string>(), It.IsAny<ViewDataDictionary>()))
.Returns(resultMock.Object);
viewComponent.Initialize(resultHelperMock.Object);
// Act // Act
var actualResult = viewComponent.View(); var actualResult = viewComponent.View();
// Assert // Assert
resultHelperMock.Verify(r => r.View("Default", viewComponent.ViewData)); Assert.IsType<ViewViewComponentResult>(actualResult);
Assert.Same(resultMock.Object, actualResult); Assert.NotSame(viewComponent.ViewData, actualResult.ViewData);
Assert.Equal(new ViewDataDictionary<object>(viewComponent.ViewData), actualResult.ViewData);
Assert.Null(actualResult.ViewData.Model);
Assert.Null(actualResult.ViewName);
} }
[Fact] [Fact]
public void ViewComponent_View_WithViewNameParameter_CallsResultViewWithCustomViewName() public void ViewComponent_View_WithViewNameParameter_SetsResultViewWithCustomViewName()
{ {
// Arrange // Arrange
var viewComponent = new TestViewComponent() var viewComponent = new TestViewComponent()
{ {
ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider()), ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider()),
}; };
var resultHelperMock = new Mock<DefaultViewComponentResultHelper>(It.IsAny<IViewEngine>());
var resultMock = new Mock<ViewViewComponentResult>(It.IsAny<IViewEngine>(),
It.IsAny<string>(),
It.IsAny<ViewDataDictionary>());
resultHelperMock.Setup(r => r.View(It.IsAny<string>(), It.IsAny<ViewDataDictionary>()))
.Returns(resultMock.Object);
viewComponent.Initialize(resultHelperMock.Object);
// Act // Act
var actualResult = viewComponent.View("CustomViewName"); var actualResult = viewComponent.View("CustomViewName");
// Assert // Assert
resultHelperMock.Verify(r => r.View("CustomViewName", viewComponent.ViewData)); Assert.IsType<ViewViewComponentResult>(actualResult);
Assert.Same(resultMock.Object, actualResult); Assert.IsType<ViewDataDictionary<object>>(actualResult.ViewData);
Assert.NotSame(viewComponent.ViewData, actualResult.ViewData);
Assert.Equal(new ViewDataDictionary<object>(viewComponent.ViewData), actualResult.ViewData);
Assert.Null(actualResult.ViewData.Model);
Assert.Equal("CustomViewName", actualResult.ViewName);
} }
[Fact] [Fact]
public void ViewComponent_View_WithModelParameter_CallsResultViewWithDefaultViewNameAndModel() public void ViewComponent_View_WithModelParameter_SetsResultViewWithDefaultViewNameAndModel()
{ {
// Arrange // Arrange
var viewComponent = new TestViewComponent() var viewComponent = new TestViewComponent()
{ {
ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider()), ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider()),
}; };
var resultHelperMock = new Mock<DefaultViewComponentResultHelper>(It.IsAny<IViewEngine>());
var resultMock = new Mock<ViewViewComponentResult>(It.IsAny<IViewEngine>(),
It.IsAny<string>(),
It.IsAny<ViewDataDictionary>());
resultHelperMock.Setup(r => r.View(It.IsAny<string>(), It.IsAny<ViewDataDictionary>()))
.Returns(resultMock.Object);
viewComponent.Initialize(resultHelperMock.Object);
var model = new object(); var model = new object();
// Act // Act
var actualResult = viewComponent.View(model); var actualResult = viewComponent.View(model);
// Assert // Assert
resultHelperMock.Verify(r => r.View("Default", viewComponent.ViewData)); Assert.IsType<ViewViewComponentResult>(actualResult);
Assert.Same(resultMock.Object, actualResult); Assert.IsType<ViewDataDictionary<object>>(actualResult.ViewData);
Assert.NotSame(viewComponent.ViewData, actualResult.ViewData);
Assert.Equal(new ViewDataDictionary<object>(viewComponent.ViewData), actualResult.ViewData);
Assert.Same(model, actualResult.ViewData.Model);
Assert.Null(actualResult.ViewName);
} }
[Fact] [Fact]
public void ViewComponent_View_WithViewNameAndModelParameters_CallsResultViewWithCustomViewNameAndModel() public void ViewComponent_View_WithViewNameAndModelParameters_SetsResultViewWithCustomViewNameAndModel()
{ {
// Arrange // Arrange
var viewComponent = new TestViewComponent() var viewComponent = new TestViewComponent()
{ {
ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider()), ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider()),
}; };
var resultHelperMock = new Mock<DefaultViewComponentResultHelper>(It.IsAny<IViewEngine>());
var resultMock = new Mock<ViewViewComponentResult>(It.IsAny<IViewEngine>(),
It.IsAny<string>(),
It.IsAny<ViewDataDictionary>());
resultHelperMock.Setup(r => r.View(It.IsAny<string>(), It.IsAny<ViewDataDictionary>()))
.Returns(resultMock.Object);
viewComponent.Initialize(resultHelperMock.Object);
var model = new object(); var model = new object();
// Act // Act
var actualResult = viewComponent.View("CustomViewName", model); var actualResult = viewComponent.View("CustomViewName", model);
// Assert // Assert
resultHelperMock.Verify(r => r.View("CustomViewName", viewComponent.ViewData)); Assert.IsType<ViewViewComponentResult>(actualResult);
Assert.Same(resultMock.Object, actualResult); Assert.IsType<ViewDataDictionary<object>>(actualResult.ViewData);
Assert.NotSame(viewComponent.ViewData, actualResult.ViewData);
Assert.Equal(new ViewDataDictionary<object>(viewComponent.ViewData), actualResult.ViewData);
Assert.Same(model, actualResult.ViewData.Model);
Assert.Equal("CustomViewName", actualResult.ViewName);
} }
private class TestViewComponent : ViewComponent private class TestViewComponent : ViewComponent