This repository has been archived by the owner on Dec 14, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
ViewViewComponentResult.cs
132 lines (115 loc) · 5.11 KB
/
ViewViewComponentResult.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.ViewEngines;
using Microsoft.AspNet.Mvc.ViewFeatures;
using Microsoft.Framework.DependencyInjection;
namespace Microsoft.AspNet.Mvc.ViewComponents
{
/// <summary>
/// A <see cref="IViewComponentResult"/> that renders a partial view when executed.
/// </summary>
public class ViewViewComponentResult : IViewComponentResult
{
// {0} is the component name, {1} is the view name.
private const string ViewPathFormat = "Components/{0}/{1}";
private const string DefaultViewName = "Default";
/// <summary>
/// Gets or sets the view name.
/// </summary>
public string ViewName { get; set; }
/// <summary>
/// Gets or sets the <see cref="ViewDataDictionary"/>.
/// </summary>
public ViewDataDictionary ViewData { get; set; }
/// <summary>
/// Gets or sets the <see cref="ITempDataDictionary"/> instance.
/// </summary>
public ITempDataDictionary TempData { get; set; }
/// <summary>
/// Gets or sets the <see cref="ViewEngine"/>.
/// </summary>
public IViewEngine ViewEngine { get; set; }
/// <summary>
/// Locates and renders a view specified by <see cref="ViewName"/>. If <see cref="ViewName"/> is <c>null</c>,
/// then the view name searched for is<c>"Default"</c>.
/// </summary>
/// <param name="context">The <see cref="ViewComponentContext"/> for the current component execution.</param>
/// <remarks>
/// This method synchronously calls and blocks on <see cref="ExecuteAsync(ViewComponentContext)"/>.
/// </remarks>
public void Execute(ViewComponentContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var task = ExecuteAsync(context);
task.GetAwaiter().GetResult();
}
/// <summary>
/// Locates and renders a view specified by <see cref="ViewName"/>. If <see cref="ViewName"/> is <c>null</c>,
/// then the view name searched for is<c>"Default"</c>.
/// </summary>
/// <param name="context">The <see cref="ViewComponentContext"/> for the current component execution.</param>
/// <returns>A <see cref="Task"/> which will complete when view rendering is completed.</returns>
public async Task ExecuteAsync(ViewComponentContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var viewEngine = ViewEngine ?? ResolveViewEngine(context);
var viewData = ViewData ?? context.ViewData;
var isNullOrEmptyViewName = string.IsNullOrEmpty(ViewName);
string qualifiedViewName;
if (!isNullOrEmptyViewName &&
(ViewName[0] == '~' || ViewName[0] == '/'))
{
// View name that was passed in is already a rooted path, the view engine will handle this.
qualifiedViewName = ViewName;
}
else
{
// This will produce a string like:
//
// Components/Cart/Default
//
// The view engine will combine this with other path info to search paths like:
//
// Views/Shared/Components/Cart/Default.cshtml
// Views/Home/Components/Cart/Default.cshtml
// Areas/Blog/Views/Shared/Components/Cart/Default.cshtml
//
// This supports a controller or area providing an override for component views.
var viewName = isNullOrEmptyViewName ? DefaultViewName : ViewName;
qualifiedViewName = string.Format(
CultureInfo.InvariantCulture,
ViewPathFormat,
context.ViewComponentDescriptor.ShortName,
viewName);
}
var view = FindView(context.ViewContext, viewEngine, qualifiedViewName);
var childViewContext = new ViewContext(
context.ViewContext,
view,
ViewData ?? context.ViewData,
context.Writer);
using (view as IDisposable)
{
await view.RenderAsync(childViewContext);
}
}
private static IView FindView(ActionContext context, IViewEngine viewEngine, string viewName)
{
return viewEngine.FindPartialView(context, viewName).EnsureSuccessful().View;
}
private static IViewEngine ResolveViewEngine(ViewComponentContext context)
{
return context.ViewContext.HttpContext.RequestServices.GetRequiredService<ICompositeViewEngine>();
}
}
}