Add `ModelMetadata` to `ViewData`
- demonstrate `ModelMetadata` is available in a view Also - simplify `View()` overloads in `Controller`, pending #110 decisions - make `Model` in `RazorView<T>` readonly
This commit is contained in:
parent
857a239990
commit
32d031c6eb
|
|
@ -10,6 +10,25 @@ namespace MvcSample.Web
|
||||||
return View("MyView", User());
|
return View("MyView", User());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Action that shows metadata when model is <c>null</c>.
|
||||||
|
/// </summary>
|
||||||
|
public IActionResult Create()
|
||||||
|
{
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Action that shows metadata when model is non-<c>null</c>.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IActionResult Edit()
|
||||||
|
{
|
||||||
|
ViewBag.Gift = "the banana";
|
||||||
|
ViewData.Model = new User { Name = "Name", Address = "Address in a State", Age = 37, };
|
||||||
|
return View("Create");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Action that exercises query\form based model binding.
|
/// Action that exercises query\form based model binding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -55,6 +74,9 @@ namespace MvcSample.Web
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Action that exercises default view names.
|
||||||
|
/// </summary>
|
||||||
public IActionResult MyView()
|
public IActionResult MyView()
|
||||||
{
|
{
|
||||||
return View(User());
|
return View(User());
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
@using MvcSample.Web.Models
|
||||||
|
@model User
|
||||||
|
@{
|
||||||
|
string nullValue = null;
|
||||||
|
ViewBag.Title = (Model == null) ? "Create Page" : "Edit Page";
|
||||||
|
if (ViewData["Gift"] == null)
|
||||||
|
{
|
||||||
|
ViewBag.Gift = "nothing";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<h2 title="@ViewBag.Title" class="@nullValue">@ViewBag.Title</h2>
|
||||||
|
<h3 title="Thanks" class="@nullValue">Thanks for @ViewBag.Gift</h3>
|
||||||
|
@if (Model == null)
|
||||||
|
{
|
||||||
|
<h4 title ="Null Model" class="@nullValue">Howdy, your model is null.</h4>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<h4 title="@Model.Name" class="@nullValue">Hello @Model.Name! Happy @Model.Age birthday.</h4>
|
||||||
|
}
|
||||||
|
|
||||||
|
@{
|
||||||
|
var metadata = ViewData.ModelMetadata;
|
||||||
|
if (metadata != null)
|
||||||
|
{
|
||||||
|
var typeName = metadata.ModelType.Name;
|
||||||
|
var description = metadata.Description;
|
||||||
|
<p>@typeName has description '@description' and contains</p>
|
||||||
|
<ul>
|
||||||
|
@foreach (var property in metadata.Properties)
|
||||||
|
{
|
||||||
|
var propertyName = property.PropertyName;
|
||||||
|
var propertyTypeName = property.ModelType.Name;
|
||||||
|
var propertyDescription = property.Description;
|
||||||
|
<li>Property @propertyName has type @propertyTypeName and description '@propertyDescription'</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
@ -33,9 +33,10 @@ namespace Microsoft.AspNet.Mvc
|
||||||
context.HttpContext.Response.ContentType = "text/html";
|
context.HttpContext.Response.ContentType = "text/html";
|
||||||
using (var writer = new StreamWriter(context.HttpContext.Response.Body, Encoding.UTF8, 1024, leaveOpen: true))
|
using (var writer = new StreamWriter(context.HttpContext.Response.Body, Encoding.UTF8, 1024, leaveOpen: true))
|
||||||
{
|
{
|
||||||
var viewContext = new ViewContext(_serviceProvider, context.HttpContext, context.RouteValues, ViewData)
|
var viewContext = new ViewContext(_serviceProvider, context.HttpContext, context.RouteValues)
|
||||||
{
|
{
|
||||||
Url = new UrlHelper(context.HttpContext, context.Router, context.RouteValues),
|
Url = new UrlHelper(context.HttpContext, context.Router, context.RouteValues),
|
||||||
|
ViewData = ViewData,
|
||||||
Writer = writer,
|
Writer = writer,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,15 @@
|
||||||
using Microsoft.AspNet.Abstractions;
|
using Microsoft.AspNet.Abstractions;
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.Rendering;
|
using Microsoft.AspNet.Mvc.Rendering;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc
|
namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
public class Controller
|
public class Controller
|
||||||
{
|
{
|
||||||
public void Initialize(IActionResultHelper actionResultHelper)
|
public void Initialize(IActionResultHelper actionResultHelper, IModelMetadataProvider metadataProvider)
|
||||||
{
|
{
|
||||||
Result = actionResultHelper;
|
Result = actionResultHelper;
|
||||||
ViewData = new ViewData<object>();
|
ViewData = new ViewData<object>(metadataProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IActionResultHelper Result { get; private set; }
|
public IActionResultHelper Result { get; private set; }
|
||||||
|
|
@ -31,21 +32,24 @@ namespace Microsoft.AspNet.Mvc
|
||||||
|
|
||||||
public IActionResult View(string view)
|
public IActionResult View(string view)
|
||||||
{
|
{
|
||||||
return View(view, model: (object)null);
|
return View(view, model: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IActionResult View<TModel>(TModel model)
|
// TODO #110: May need <TModel> here and in the overload below.
|
||||||
|
public IActionResult View(object model)
|
||||||
{
|
{
|
||||||
return View(view: null, model: model);
|
return View(view: null, model: model);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IActionResult View<TModel>(string view, TModel model)
|
public IActionResult View(string view, object model)
|
||||||
{
|
{
|
||||||
var viewDataDictionary = new ViewData<TModel>
|
// Do not override ViewData.Model unless passed a non-null value.
|
||||||
|
if (model != null)
|
||||||
{
|
{
|
||||||
Model = model
|
ViewData.Model = model;
|
||||||
};
|
}
|
||||||
return Result.View(view, viewDataDictionary);
|
|
||||||
|
return Result.View(view, ViewData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
|
||||||
private string BodyContent { get; set; }
|
private string BodyContent { get; set; }
|
||||||
|
|
||||||
public virtual async Task RenderAsync(ViewContext context, TextWriter writer)
|
public virtual async Task RenderAsync([NotNull] ViewContext context, [NotNull] TextWriter writer)
|
||||||
{
|
{
|
||||||
Context = context;
|
Context = context;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,49 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.DependencyInjection;
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.Rendering;
|
using Microsoft.AspNet.Mvc.Rendering;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.Razor
|
namespace Microsoft.AspNet.Mvc.Razor
|
||||||
{
|
{
|
||||||
public abstract class RazorView<TModel> : RazorView
|
public abstract class RazorView<TModel> : RazorView
|
||||||
{
|
{
|
||||||
public TModel Model { get; set; }
|
public TModel Model
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ViewData == null ? default(TModel) : ViewData.Model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public dynamic ViewBag
|
public dynamic ViewBag
|
||||||
{
|
{
|
||||||
get { return ViewData; }
|
get { return ViewData; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public ViewData<TModel> ViewData { get; set; }
|
public ViewData<TModel> ViewData { get; private set; }
|
||||||
|
|
||||||
public HtmlHelper<TModel> Html { get; set; }
|
public HtmlHelper<TModel> Html { get; set; }
|
||||||
|
|
||||||
public override Task RenderAsync(ViewContext context, TextWriter writer)
|
public override Task RenderAsync([NotNull] ViewContext context, [NotNull] TextWriter writer)
|
||||||
{
|
{
|
||||||
var viewData = context.ViewData as ViewData<TModel>;
|
ViewData = context.ViewData as ViewData<TModel>;
|
||||||
ViewData = viewData ?? new ViewData<TModel>(context.ViewData);
|
if (ViewData == null)
|
||||||
Model = ViewData.Model;
|
{
|
||||||
|
if (context.ViewData != null)
|
||||||
|
{
|
||||||
|
ViewData = new ViewData<TModel>(context.ViewData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var metadataProvider = context.ServiceProvider.GetService<IModelMetadataProvider>();
|
||||||
|
ViewData = new ViewData<TModel>(metadataProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Have new ViewData; make sure it's visible everywhere.
|
||||||
|
context.ViewData = ViewData;
|
||||||
|
}
|
||||||
|
|
||||||
InitHelpers(context);
|
InitHelpers(context);
|
||||||
|
|
||||||
return base.RenderAsync(context, writer);
|
return base.RenderAsync(context, writer);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,6 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
{
|
{
|
||||||
public interface IView
|
public interface IView
|
||||||
{
|
{
|
||||||
Task RenderAsync(ViewContext context, TextWriter writer);
|
Task RenderAsync([NotNull] ViewContext context, [NotNull] TextWriter writer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
{
|
{
|
||||||
public class ViewContext
|
public class ViewContext
|
||||||
{
|
{
|
||||||
public ViewContext(IServiceProvider serviceProvider, HttpContext httpContext, IDictionary<string, object> viewEngineContext, ViewData viewData)
|
public ViewContext(IServiceProvider serviceProvider, HttpContext httpContext, IDictionary<string, object> viewEngineContext)
|
||||||
{
|
{
|
||||||
ServiceProvider = serviceProvider;
|
ServiceProvider = serviceProvider;
|
||||||
HttpContext = httpContext;
|
HttpContext = httpContext;
|
||||||
ViewEngineContext = viewEngineContext;
|
ViewEngineContext = viewEngineContext;
|
||||||
ViewData = viewData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpContext HttpContext { get; private set; }
|
public HttpContext HttpContext { get; private set; }
|
||||||
|
|
@ -21,7 +20,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
|
|
||||||
public IUrlHelper Url { get; set; }
|
public IUrlHelper Url { get; set; }
|
||||||
|
|
||||||
public ViewData ViewData { get; private set; }
|
public ViewData ViewData { get; set; }
|
||||||
|
|
||||||
public IDictionary<string, object> ViewEngineContext { get; private set; }
|
public IDictionary<string, object> ViewEngineContext { get; private set; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Dynamic;
|
using System.Dynamic;
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.Rendering
|
namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
{
|
{
|
||||||
|
|
@ -8,15 +9,20 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
{
|
{
|
||||||
private readonly Dictionary<object, dynamic> _data;
|
private readonly Dictionary<object, dynamic> _data;
|
||||||
private object _model;
|
private object _model;
|
||||||
|
private ModelMetadata _modelMetadata;
|
||||||
|
private IModelMetadataProvider _metadataProvider;
|
||||||
|
|
||||||
public ViewData()
|
public ViewData([NotNull] IModelMetadataProvider metadataProvider)
|
||||||
{
|
{
|
||||||
_data = new Dictionary<object, dynamic>();
|
_data = new Dictionary<object, dynamic>();
|
||||||
|
_metadataProvider = metadataProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ViewData([NotNull] ViewData source)
|
public ViewData([NotNull] ViewData source)
|
||||||
{
|
{
|
||||||
_data = source._data;
|
_data = source._data;
|
||||||
|
_modelMetadata = source.ModelMetadata;
|
||||||
|
_metadataProvider = source.MetadataProvider;
|
||||||
SetModel(source.Model);
|
SetModel(source.Model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,13 +50,34 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_data[index] = (dynamic)value;
|
_data[index] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual ModelMetadata ModelMetadata
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _modelMetadata;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_modelMetadata = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provider for subclasses that need it to override <see cref="ModelMetadata"/>.
|
||||||
|
/// </summary>
|
||||||
|
protected IModelMetadataProvider MetadataProvider
|
||||||
|
{
|
||||||
|
get { return _metadataProvider; }
|
||||||
|
}
|
||||||
|
|
||||||
public override bool TryGetMember(GetMemberBinder binder, out object result)
|
public override bool TryGetMember(GetMemberBinder binder, out object result)
|
||||||
{
|
{
|
||||||
result = _data[binder.Name];
|
result = _data[binder.Name];
|
||||||
|
|
||||||
// We return true here because ViewDataDictionary returns null if the key is not
|
// We return true here because ViewDataDictionary returns null if the key is not
|
||||||
// in the dictionary, so we simply pass on the returned value.
|
// in the dictionary, so we simply pass on the returned value.
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -58,7 +85,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
|
|
||||||
public override bool TrySetMember(SetMemberBinder binder, object value)
|
public override bool TrySetMember(SetMemberBinder binder, object value)
|
||||||
{
|
{
|
||||||
// This cast should always succeed assuming TValue is dynamic.
|
// This cast should always succeed.
|
||||||
dynamic v = value;
|
dynamic v = value;
|
||||||
_data[binder.Name] = v;
|
_data[binder.Name] = v;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -84,7 +111,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
}
|
}
|
||||||
|
|
||||||
object index = indexes[0];
|
object index = indexes[0];
|
||||||
// This cast should always succeed assuming TValue is dynamic.
|
|
||||||
|
// This cast should always succeed.
|
||||||
this[(string)index] = value;
|
this[(string)index] = value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -95,6 +123,16 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
protected virtual void SetModel(object value)
|
protected virtual void SetModel(object value)
|
||||||
{
|
{
|
||||||
_model = value;
|
_model = value;
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
// Unable to determine model metadata.
|
||||||
|
_modelMetadata = null;
|
||||||
|
}
|
||||||
|
else if (_modelMetadata == null || value.GetType() != ModelMetadata.ModelType)
|
||||||
|
{
|
||||||
|
// Reset or override model metadata based on new value type.
|
||||||
|
_modelMetadata = _metadataProvider.GetMetadataForType(() => value, value.GetType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,32 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding.Internal;
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.Rendering
|
namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
{
|
{
|
||||||
public class ViewData<TModel> : ViewData
|
public class ViewData<TModel> : ViewData
|
||||||
{
|
{
|
||||||
public ViewData()
|
// Fallback ModelMetadata based on TModel. Used when Model is null and base ViewData class is unable to
|
||||||
: base()
|
// determine the correct metadata.
|
||||||
|
private readonly ModelMetadata _defaultModelMetadata;
|
||||||
|
|
||||||
|
public ViewData([NotNull] IModelMetadataProvider metadataProvider)
|
||||||
|
: base(metadataProvider)
|
||||||
{
|
{
|
||||||
|
_defaultModelMetadata = MetadataProvider.GetMetadataForType(null, typeof(TModel));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ViewData(ViewData source) :
|
public ViewData(ViewData source)
|
||||||
base(source)
|
: base(source)
|
||||||
{
|
{
|
||||||
|
var original = source as ViewData<TModel>;
|
||||||
|
if (original != null)
|
||||||
|
{
|
||||||
|
_defaultModelMetadata = original._defaultModelMetadata;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_defaultModelMetadata = MetadataProvider.GetMetadataForType(null, typeof(TModel));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public new TModel Model
|
public new TModel Model
|
||||||
|
|
@ -21,6 +35,14 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
set { SetModel(value); }
|
set { SetModel(value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override ModelMetadata ModelMetadata
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return base.ModelMetadata ?? _defaultModelMetadata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override void SetModel(object value)
|
protected override void SetModel(object value)
|
||||||
{
|
{
|
||||||
// IsCompatibleObject verifies if the value is either an instance of TModel or (if value is null) that
|
// IsCompatibleObject verifies if the value is either an instance of TModel or (if value is null) that
|
||||||
|
|
@ -42,6 +64,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
{
|
{
|
||||||
message = Resources.FormatViewData_WrongTModelType(value.GetType(), typeof(TModel));
|
message = Resources.FormatViewData_WrongTModelType(value.GetType(), typeof(TModel));
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new InvalidOperationException(message);
|
throw new InvalidOperationException(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.Rendering.Test
|
namespace Microsoft.AspNet.Mvc.Rendering
|
||||||
{
|
{
|
||||||
public class ViewDataOfTTest
|
public class ViewDataOfTTest
|
||||||
{
|
{
|
||||||
|
|
@ -9,7 +10,7 @@ namespace Microsoft.AspNet.Mvc.Rendering.Test
|
||||||
public void SettingModelThrowsIfTheModelIsNull()
|
public void SettingModelThrowsIfTheModelIsNull()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var viewDataOfT = new ViewData<int>();
|
var viewDataOfT = new ViewData<int>(new DataAnnotationsModelMetadataProvider());
|
||||||
ViewData viewData = viewDataOfT;
|
ViewData viewData = viewDataOfT;
|
||||||
|
|
||||||
// Act and Assert
|
// Act and Assert
|
||||||
|
|
@ -21,7 +22,7 @@ namespace Microsoft.AspNet.Mvc.Rendering.Test
|
||||||
public void SettingModelThrowsIfTheModelIsIncompatible()
|
public void SettingModelThrowsIfTheModelIsIncompatible()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var viewDataOfT = new ViewData<string>();
|
var viewDataOfT = new ViewData<string>(new DataAnnotationsModelMetadataProvider());
|
||||||
ViewData viewData = viewDataOfT;
|
ViewData viewData = viewDataOfT;
|
||||||
|
|
||||||
// Act and Assert
|
// Act and Assert
|
||||||
|
|
@ -34,7 +35,7 @@ namespace Microsoft.AspNet.Mvc.Rendering.Test
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
string value = "some value";
|
string value = "some value";
|
||||||
var viewDataOfT = new ViewData<object>();
|
var viewDataOfT = new ViewData<object>(new DataAnnotationsModelMetadataProvider());
|
||||||
ViewData viewData = viewDataOfT;
|
ViewData viewData = viewDataOfT;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.AspNet.Abstractions": "0.1-alpha-*",
|
"Microsoft.AspNet.Abstractions": "0.1-alpha-*",
|
||||||
"Microsoft.AspNet.PipelineCore": "0.1-alpha-*",
|
"Microsoft.AspNet.PipelineCore": "0.1-alpha-*",
|
||||||
|
"Microsoft.AspNet.Mvc.ModelBinding" : "",
|
||||||
"Microsoft.AspNet.Mvc.Rendering" : "",
|
"Microsoft.AspNet.Mvc.Rendering" : "",
|
||||||
"TestCommon" : "",
|
"TestCommon" : "",
|
||||||
"Xunit.KRunner": "0.1-alpha-*",
|
"Xunit.KRunner": "0.1-alpha-*",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue