parent
1118315a9d
commit
1af1583302
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
namespace System.Web.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// Controls interpretation of a controller name when constructing a <see cref="RemoteAttribute"/>.
|
||||
/// </summary>
|
||||
public enum AreaReference
|
||||
{
|
||||
/// <summary>
|
||||
/// Find the controller in the current area.
|
||||
/// </summary>
|
||||
UseCurrent = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Find the controller in the root area.
|
||||
/// </summary>
|
||||
UseRoot = 1,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace System.Web.Mvc
|
||||
{
|
||||
[TypeForwardedFrom("System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")]
|
||||
public class ModelClientValidationRemoteRule : ModelClientValidationRule
|
||||
{
|
||||
[SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", Justification = "The value is a not a regular URL since it may contain ~/ ASP.NET-specific characters")]
|
||||
public ModelClientValidationRemoteRule(string errorMessage, string url, string httpMethod, string additionalFields)
|
||||
{
|
||||
ErrorMessage = errorMessage;
|
||||
ValidationType = "remote";
|
||||
ValidationParameters["url"] = url;
|
||||
|
||||
if (!String.IsNullOrEmpty(httpMethod))
|
||||
{
|
||||
ValidationParameters["type"] = httpMethod;
|
||||
}
|
||||
|
||||
ValidationParameters["additionalfields"] = additionalFields;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Web.Mvc.Properties;
|
||||
using System.Web.Routing;
|
||||
|
||||
namespace System.Web.Mvc
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
[SuppressMessage("Microsoft.Design", "CA1019:DefineAccessorsForAttributeArguments", Justification = "The constructor parameters are used to feed RouteData, which is public.")]
|
||||
[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "This attribute is designed to be a base class for other attributes.")]
|
||||
public class RemoteAttribute : ValidationAttribute, IClientValidatable
|
||||
{
|
||||
private string _additionalFields;
|
||||
private string[] _additonalFieldsSplit = new string[0];
|
||||
|
||||
protected RemoteAttribute()
|
||||
: base(MvcResources.RemoteAttribute_RemoteValidationFailed)
|
||||
{
|
||||
RouteData = new RouteValueDictionary();
|
||||
}
|
||||
|
||||
public RemoteAttribute(string routeName)
|
||||
: this()
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(routeName))
|
||||
{
|
||||
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "routeName");
|
||||
}
|
||||
|
||||
RouteName = routeName;
|
||||
}
|
||||
|
||||
public RemoteAttribute(string action, string controller)
|
||||
:
|
||||
this(action, controller, null /* areaName */)
|
||||
{
|
||||
}
|
||||
|
||||
public RemoteAttribute(string action, string controller, string areaName)
|
||||
: this()
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(action))
|
||||
{
|
||||
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "action");
|
||||
}
|
||||
if (String.IsNullOrWhiteSpace(controller))
|
||||
{
|
||||
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "controller");
|
||||
}
|
||||
|
||||
RouteData["controller"] = controller;
|
||||
RouteData["action"] = action;
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(areaName))
|
||||
{
|
||||
RouteData["area"] = areaName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RemoteAttribute"/> class.
|
||||
/// </summary>
|
||||
/// <param name="action">The route name.</param>
|
||||
/// <param name="controller">The name of the controller.</param>
|
||||
/// <param name="areaReference">
|
||||
/// Find the controller in the root if <see cref="AreaReference.UseRoot"/>. Otherwise look in the current area.
|
||||
/// </param>
|
||||
public RemoteAttribute(string action, string controller, AreaReference areaReference)
|
||||
: this(action, controller)
|
||||
{
|
||||
if (areaReference == AreaReference.UseRoot)
|
||||
{
|
||||
RouteData["area"] = null;
|
||||
}
|
||||
}
|
||||
|
||||
public string HttpMethod { get; set; }
|
||||
|
||||
public string AdditionalFields
|
||||
{
|
||||
get { return _additionalFields ?? String.Empty; }
|
||||
set
|
||||
{
|
||||
_additionalFields = value;
|
||||
_additonalFieldsSplit = AuthorizeAttribute.SplitString(value);
|
||||
}
|
||||
}
|
||||
|
||||
protected RouteValueDictionary RouteData { get; private set; }
|
||||
|
||||
protected string RouteName { get; set; }
|
||||
|
||||
protected virtual RouteCollection Routes
|
||||
{
|
||||
get { return RouteTable.Routes; }
|
||||
}
|
||||
|
||||
public string FormatAdditionalFieldsForClientValidation(string property)
|
||||
{
|
||||
if (String.IsNullOrEmpty(property))
|
||||
{
|
||||
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "property");
|
||||
}
|
||||
|
||||
string delimitedAdditionalFields = FormatPropertyForClientValidation(property);
|
||||
|
||||
foreach (string field in _additonalFieldsSplit)
|
||||
{
|
||||
delimitedAdditionalFields += "," + FormatPropertyForClientValidation(field);
|
||||
}
|
||||
|
||||
return delimitedAdditionalFields;
|
||||
}
|
||||
|
||||
public static string FormatPropertyForClientValidation(string property)
|
||||
{
|
||||
if (String.IsNullOrEmpty(property))
|
||||
{
|
||||
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "property");
|
||||
}
|
||||
return "*." + property;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings", Justification = "The value is a not a regular URL since it may contain ~/ ASP.NET-specific characters")]
|
||||
protected virtual string GetUrl(ControllerContext controllerContext)
|
||||
{
|
||||
var pathData = Routes.GetVirtualPathForArea(controllerContext.RequestContext,
|
||||
RouteName,
|
||||
RouteData);
|
||||
|
||||
if (pathData == null)
|
||||
{
|
||||
throw new InvalidOperationException(MvcResources.RemoteAttribute_NoUrlFound);
|
||||
}
|
||||
|
||||
return pathData.VirtualPath;
|
||||
}
|
||||
|
||||
public override string FormatErrorMessage(string name)
|
||||
{
|
||||
return String.Format(CultureInfo.CurrentCulture, ErrorMessageString, name);
|
||||
}
|
||||
|
||||
public override bool IsValid(object value)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
|
||||
{
|
||||
yield return new ModelClientValidationRemoteRule(FormatErrorMessage(metadata.GetDisplayName()), GetUrl(context), HttpMethod, FormatAdditionalFieldsForClientValidation(metadata.PropertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,467 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Routing;
|
||||
using Microsoft.TestCommon;
|
||||
using Moq;
|
||||
|
||||
namespace System.Web.Mvc.Test
|
||||
{
|
||||
public class RemoteAttributeTest
|
||||
{
|
||||
// Good route name, bad route name
|
||||
// Controller + Action
|
||||
|
||||
[Fact]
|
||||
public void GuardClauses()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.ThrowsArgumentNullOrEmpty(
|
||||
() => new RemoteAttribute(null, "controller"),
|
||||
"action");
|
||||
Assert.ThrowsArgumentNullOrEmpty(
|
||||
() => new RemoteAttribute("action", null),
|
||||
"controller");
|
||||
Assert.ThrowsArgumentNullOrEmpty(
|
||||
() => new RemoteAttribute(null),
|
||||
"routeName");
|
||||
Assert.ThrowsArgumentNullOrEmpty(
|
||||
() => RemoteAttribute.FormatPropertyForClientValidation(String.Empty),
|
||||
"property");
|
||||
Assert.ThrowsArgumentNullOrEmpty(
|
||||
() => new RemoteAttribute("foo").FormatAdditionalFieldsForClientValidation(String.Empty),
|
||||
"property");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsValidAlwaysReturnsTrue()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.True(new RemoteAttribute("RouteName", "ParameterName").IsValid(null));
|
||||
Assert.True(new RemoteAttribute("ActionName", "ControllerName", "ParameterName").IsValid(null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BadRouteNameThrows()
|
||||
{
|
||||
// Arrange
|
||||
ControllerContext context = new ControllerContext();
|
||||
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(object));
|
||||
TestableRemoteAttribute attribute = new TestableRemoteAttribute("RouteName");
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentException>(
|
||||
() => new List<ModelClientValidationRule>(attribute.GetClientValidationRules(metadata, context)),
|
||||
"A route named 'RouteName' could not be found in the route collection.\r\nParameter name: name");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NoRouteWithActionControllerThrows()
|
||||
{
|
||||
// Arrange
|
||||
ControllerContext context = new ControllerContext();
|
||||
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForProperty(null, typeof(string), "Length");
|
||||
TestableRemoteAttribute attribute = new TestableRemoteAttribute("Action", "Controller");
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
() => new List<ModelClientValidationRule>(attribute.GetClientValidationRules(metadata, context)),
|
||||
"No url for remote validation could be found.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GoodRouteNameReturnsCorrectClientData()
|
||||
{
|
||||
// Arrange
|
||||
string url = null;
|
||||
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForProperty(null, typeof(string), "Length");
|
||||
TestableRemoteAttribute attribute = new TestableRemoteAttribute("RouteName");
|
||||
attribute.RouteTable.Add("RouteName", new Route("my/url", new MvcRouteHandler()));
|
||||
|
||||
// Act
|
||||
ModelClientValidationRule rule = attribute.GetClientValidationRules(metadata, GetMockControllerContext(url)).Single();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("remote", rule.ValidationType);
|
||||
Assert.Equal("'Length' is invalid.", rule.ErrorMessage);
|
||||
Assert.Equal(2, rule.ValidationParameters.Count);
|
||||
Assert.Equal("/my/url", rule.ValidationParameters["url"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ActionControllerReturnsCorrectClientDataWithoutNamedParameters()
|
||||
{
|
||||
// Arrange
|
||||
string url = null;
|
||||
|
||||
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForProperty(null, typeof(string), "Length");
|
||||
TestableRemoteAttribute attribute = new TestableRemoteAttribute("Action", "Controller");
|
||||
attribute.RouteTable.Add(new Route("{controller}/{action}", new MvcRouteHandler()));
|
||||
|
||||
// Act
|
||||
ModelClientValidationRule rule = attribute.GetClientValidationRules(metadata, GetMockControllerContext(url)).Single();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("remote", rule.ValidationType);
|
||||
Assert.Equal("'Length' is invalid.", rule.ErrorMessage);
|
||||
Assert.Equal(2, rule.ValidationParameters.Count);
|
||||
Assert.Equal("/Controller/Action", rule.ValidationParameters["url"]);
|
||||
Assert.Equal("*.Length", rule.ValidationParameters["additionalfields"]);
|
||||
Assert.Throws<KeyNotFoundException>(
|
||||
() => rule.ValidationParameters["type"],
|
||||
"The given key was not present in the dictionary.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ActionControllerReturnsCorrectClientDataWithNamedParameters()
|
||||
{
|
||||
// Arrange
|
||||
string url = null;
|
||||
|
||||
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForProperty(null, typeof(string), "Length");
|
||||
TestableRemoteAttribute attribute = new TestableRemoteAttribute("Action", "Controller");
|
||||
attribute.HttpMethod = "POST";
|
||||
attribute.AdditionalFields = "Password,ConfirmPassword";
|
||||
|
||||
attribute.RouteTable.Add(new Route("{controller}/{action}", new MvcRouteHandler()));
|
||||
|
||||
// Act
|
||||
ModelClientValidationRule rule = attribute.GetClientValidationRules(metadata, GetMockControllerContext(url)).Single();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("remote", rule.ValidationType);
|
||||
Assert.Equal("'Length' is invalid.", rule.ErrorMessage);
|
||||
Assert.Equal(3, rule.ValidationParameters.Count);
|
||||
Assert.Equal("/Controller/Action", rule.ValidationParameters["url"]);
|
||||
Assert.Equal("*.Length,*.Password,*.ConfirmPassword", rule.ValidationParameters["additionalfields"]);
|
||||
Assert.Equal("POST", rule.ValidationParameters["type"]);
|
||||
}
|
||||
|
||||
// Current area is root in this case.
|
||||
[Fact]
|
||||
public void ActionController_RemoteFindsControllerInCurrentArea()
|
||||
{
|
||||
// Arrange
|
||||
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForProperty(modelAccessor: null,
|
||||
containerType: typeof(string), propertyName: "Length");
|
||||
TestableRemoteAttribute attribute = new TestableRemoteAttribute("Action", "Controller");
|
||||
attribute.HttpMethod = "POST";
|
||||
|
||||
var context = new AreaRegistrationContext("Test", attribute.RouteTable);
|
||||
context.MapRoute(name: null, url: "Test/{controller}/{action}");
|
||||
|
||||
attribute.RouteTable.Add(new Route("{controller}/{action}", new MvcRouteHandler()));
|
||||
|
||||
// Act
|
||||
ModelClientValidationRule rule =
|
||||
attribute.GetClientValidationRules(metadata, GetMockControllerContext(url: null)).Single();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("remote", rule.ValidationType);
|
||||
Assert.Equal("/Controller/Action", rule.ValidationParameters["url"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ActionControllerArea_RemoteFindsControllerInNamedArea()
|
||||
{
|
||||
// Arrange
|
||||
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForProperty(modelAccessor: null,
|
||||
containerType: typeof(string), propertyName: "Length");
|
||||
TestableRemoteAttribute attribute = new TestableRemoteAttribute("Action", "Controller", "Test");
|
||||
attribute.HttpMethod = "POST";
|
||||
|
||||
var context = new AreaRegistrationContext("Test", attribute.RouteTable);
|
||||
context.MapRoute(name: null, url: "Test/{controller}/{action}");
|
||||
|
||||
attribute.RouteTable.Add(new Route("{controller}/{action}", new MvcRouteHandler()));
|
||||
|
||||
// Act
|
||||
ModelClientValidationRule rule =
|
||||
attribute.GetClientValidationRules(metadata, GetMockControllerContext(url: null)).Single();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("remote", rule.ValidationType);
|
||||
Assert.Equal("/Test/Controller/Action", rule.ValidationParameters["url"]);
|
||||
}
|
||||
|
||||
// Current area is root in this case.
|
||||
[Fact]
|
||||
public void ActionControllerArea_WithEmptyArea_RemoteFindsControllerInCurrentArea()
|
||||
{
|
||||
// Arrange
|
||||
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForProperty(modelAccessor: null,
|
||||
containerType: typeof(string), propertyName: "Length");
|
||||
TestableRemoteAttribute attribute = new TestableRemoteAttribute("Action", "Controller", "");
|
||||
attribute.HttpMethod = "POST";
|
||||
|
||||
var context = new AreaRegistrationContext("Test", attribute.RouteTable);
|
||||
context.MapRoute(name: null, url: "Test/{controller}/{action}");
|
||||
|
||||
attribute.RouteTable.Add(new Route("{controller}/{action}", new MvcRouteHandler()));
|
||||
|
||||
// Act
|
||||
ModelClientValidationRule rule =
|
||||
attribute.GetClientValidationRules(metadata, GetMockControllerContext(url: null)).Single();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("remote", rule.ValidationType);
|
||||
Assert.Equal("/Controller/Action", rule.ValidationParameters["url"]);
|
||||
}
|
||||
|
||||
// Current area is root in this case.
|
||||
[Fact]
|
||||
public void ActionControllerAreaReference_WithUseCurrent_RemoteFindsControllerInCurrentArea()
|
||||
{
|
||||
// Arrange
|
||||
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForProperty(modelAccessor: null,
|
||||
containerType: typeof(string), propertyName: "Length");
|
||||
TestableRemoteAttribute attribute = new TestableRemoteAttribute("Action", "Controller", AreaReference.UseCurrent);
|
||||
attribute.HttpMethod = "POST";
|
||||
|
||||
var context = new AreaRegistrationContext("Test", attribute.RouteTable);
|
||||
context.MapRoute(name: null, url: "Test/{controller}/{action}");
|
||||
|
||||
attribute.RouteTable.Add(new Route("{controller}/{action}", new MvcRouteHandler()));
|
||||
|
||||
// Act
|
||||
ModelClientValidationRule rule =
|
||||
attribute.GetClientValidationRules(metadata, GetMockControllerContext(url: null)).Single();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("remote", rule.ValidationType);
|
||||
Assert.Equal("/Controller/Action", rule.ValidationParameters["url"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ActionControllerAreaReference_WithUseRoot_RemoteFindsControllerInRoot()
|
||||
{
|
||||
// Arrange
|
||||
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForProperty(modelAccessor: null,
|
||||
containerType: typeof(string), propertyName: "Length");
|
||||
TestableRemoteAttribute attribute = new TestableRemoteAttribute("Action", "Controller", AreaReference.UseRoot);
|
||||
attribute.HttpMethod = "POST";
|
||||
|
||||
var context = new AreaRegistrationContext("Test", attribute.RouteTable);
|
||||
context.MapRoute(name: null, url: "Test/{controller}/{action}");
|
||||
|
||||
attribute.RouteTable.Add(new Route("{controller}/{action}", new MvcRouteHandler()));
|
||||
|
||||
// Act
|
||||
ModelClientValidationRule rule =
|
||||
attribute.GetClientValidationRules(metadata, GetMockControllerContext(url: null)).Single();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("remote", rule.ValidationType);
|
||||
Assert.Equal("/Controller/Action", rule.ValidationParameters["url"]);
|
||||
}
|
||||
|
||||
// Current area is Test in this case.
|
||||
[Fact]
|
||||
public void ActionController_InArea_RemoteFindsControllerInCurrentArea()
|
||||
{
|
||||
// Arrange
|
||||
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForProperty(modelAccessor: null,
|
||||
containerType: typeof(string), propertyName: "Length");
|
||||
TestableRemoteAttribute attribute = new TestableRemoteAttribute("Action", "Controller");
|
||||
attribute.HttpMethod = "POST";
|
||||
|
||||
var context = new AreaRegistrationContext("Test", attribute.RouteTable);
|
||||
context.MapRoute(name: null, url: "Test/{controller}/{action}");
|
||||
|
||||
attribute.RouteTable.Add(new Route("{controller}/{action}", new MvcRouteHandler()));
|
||||
|
||||
// Act
|
||||
ModelClientValidationRule rule =
|
||||
attribute.GetClientValidationRules(metadata, GetMockControllerContextWithArea(url: null, areaName: "Test"))
|
||||
.Single();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("remote", rule.ValidationType);
|
||||
Assert.Equal("/Test/Controller/Action", rule.ValidationParameters["url"]);
|
||||
}
|
||||
|
||||
// Explicit reference to the Test area.
|
||||
[Fact]
|
||||
public void ActionControllerArea_InSameArea_RemoteFindsControllerInNamedArea()
|
||||
{
|
||||
// Arrange
|
||||
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForProperty(modelAccessor: null,
|
||||
containerType: typeof(string), propertyName: "Length");
|
||||
TestableRemoteAttribute attribute = new TestableRemoteAttribute("Action", "Controller", "Test");
|
||||
attribute.HttpMethod = "POST";
|
||||
|
||||
var context = new AreaRegistrationContext("Test", attribute.RouteTable);
|
||||
context.MapRoute(name: null, url: "Test/{controller}/{action}");
|
||||
|
||||
attribute.RouteTable.Add(new Route("{controller}/{action}", new MvcRouteHandler()));
|
||||
|
||||
// Act
|
||||
ModelClientValidationRule rule =
|
||||
attribute.GetClientValidationRules(metadata, GetMockControllerContextWithArea(url: null, areaName: "Test"))
|
||||
.Single();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("remote", rule.ValidationType);
|
||||
Assert.Equal("/Test/Controller/Action", rule.ValidationParameters["url"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ActionControllerArea_InArea_RemoteFindsControllerInNamedArea()
|
||||
{
|
||||
// Arrange
|
||||
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForProperty(modelAccessor: null,
|
||||
containerType: typeof(string), propertyName: "Length");
|
||||
TestableRemoteAttribute attribute = new TestableRemoteAttribute("Action", "Controller", "AnotherArea");
|
||||
attribute.HttpMethod = "POST";
|
||||
|
||||
var context = new AreaRegistrationContext("Test", attribute.RouteTable);
|
||||
context.MapRoute(name: null, url: "Test/{controller}/{action}");
|
||||
context = new AreaRegistrationContext("AnotherArea", attribute.RouteTable);
|
||||
context.MapRoute(name: null, url: "AnotherArea/{controller}/{action}");
|
||||
|
||||
attribute.RouteTable.Add(new Route("{controller}/{action}", new MvcRouteHandler()));
|
||||
|
||||
// Act
|
||||
ModelClientValidationRule rule =
|
||||
attribute.GetClientValidationRules(metadata, GetMockControllerContextWithArea(url: null, areaName: "Test"))
|
||||
.Single();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("remote", rule.ValidationType);
|
||||
Assert.Equal("/AnotherArea/Controller/Action", rule.ValidationParameters["url"]);
|
||||
}
|
||||
|
||||
// Current area is Test in this case.
|
||||
[Fact]
|
||||
public void ActionControllerArea_WithEmptyAreaInArea_RemoteFindsControllerInCurrentArea()
|
||||
{
|
||||
// Arrange
|
||||
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForProperty(modelAccessor: null,
|
||||
containerType: typeof(string), propertyName: "Length");
|
||||
TestableRemoteAttribute attribute = new TestableRemoteAttribute("Action", "Controller", "");
|
||||
attribute.HttpMethod = "POST";
|
||||
|
||||
var context = new AreaRegistrationContext("Test", attribute.RouteTable);
|
||||
context.MapRoute(name: null, url: "Test/{controller}/{action}");
|
||||
|
||||
attribute.RouteTable.Add(new Route("{controller}/{action}", new MvcRouteHandler()));
|
||||
|
||||
// Act
|
||||
ModelClientValidationRule rule =
|
||||
attribute.GetClientValidationRules(metadata, GetMockControllerContextWithArea(url: null, areaName: "Test"))
|
||||
.Single();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("remote", rule.ValidationType);
|
||||
Assert.Equal("/Test/Controller/Action", rule.ValidationParameters["url"]);
|
||||
}
|
||||
|
||||
// Current area is Test in this case.
|
||||
[Fact]
|
||||
public void ActionControllerAreaReference_WithUseCurrentInArea_RemoteFindsControllerInCurrentArea()
|
||||
{
|
||||
// Arrange
|
||||
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForProperty(modelAccessor: null,
|
||||
containerType: typeof(string), propertyName: "Length");
|
||||
TestableRemoteAttribute attribute = new TestableRemoteAttribute("Action", "Controller", AreaReference.UseCurrent);
|
||||
attribute.HttpMethod = "POST";
|
||||
|
||||
var context = new AreaRegistrationContext("Test", attribute.RouteTable);
|
||||
context.MapRoute(name: null, url: "Test/{controller}/{action}");
|
||||
|
||||
attribute.RouteTable.Add(new Route("{controller}/{action}", new MvcRouteHandler()));
|
||||
|
||||
// Act
|
||||
ModelClientValidationRule rule =
|
||||
attribute.GetClientValidationRules(metadata, GetMockControllerContextWithArea(url: null, areaName: "Test"))
|
||||
.Single();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("remote", rule.ValidationType);
|
||||
Assert.Equal("/Test/Controller/Action", rule.ValidationParameters["url"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ActionControllerAreaReference_WithUseRootInArea_RemoteFindsControllerInRoot()
|
||||
{
|
||||
// Arrange
|
||||
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForProperty(modelAccessor: null,
|
||||
containerType: typeof(string), propertyName: "Length");
|
||||
TestableRemoteAttribute attribute = new TestableRemoteAttribute("Action", "Controller", AreaReference.UseRoot);
|
||||
attribute.HttpMethod = "POST";
|
||||
|
||||
var context = new AreaRegistrationContext("Test", attribute.RouteTable);
|
||||
context.MapRoute(name: null, url: "Test/{controller}/{action}");
|
||||
|
||||
attribute.RouteTable.Add(new Route("{controller}/{action}", new MvcRouteHandler()));
|
||||
|
||||
// Act
|
||||
ModelClientValidationRule rule =
|
||||
attribute.GetClientValidationRules(metadata, GetMockControllerContextWithArea(url: null, areaName: "Test"))
|
||||
.Single();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("remote", rule.ValidationType);
|
||||
Assert.Equal("/Controller/Action", rule.ValidationParameters["url"]);
|
||||
}
|
||||
|
||||
private ControllerContext GetMockControllerContext(string url)
|
||||
{
|
||||
Mock<ControllerContext> context = new Mock<ControllerContext>();
|
||||
context.Setup(c => c.HttpContext.Request.ApplicationPath)
|
||||
.Returns("/");
|
||||
context.Setup(c => c.HttpContext.Response.ApplyAppPathModifier(It.IsAny<string>()))
|
||||
.Callback<string>(vpath => url = vpath)
|
||||
.Returns(() => url);
|
||||
|
||||
return context.Object;
|
||||
}
|
||||
|
||||
private ControllerContext GetMockControllerContextWithArea(string url, string areaName)
|
||||
{
|
||||
Mock<ControllerContext> context = new Mock<ControllerContext>();
|
||||
context.Setup(c => c.HttpContext.Request.ApplicationPath)
|
||||
.Returns("/");
|
||||
context.Setup(c => c.HttpContext.Response.ApplyAppPathModifier(It.IsAny<string>()))
|
||||
.Callback<string>(vpath => url = vpath)
|
||||
.Returns(() => url);
|
||||
|
||||
var controllerContext = context.Object;
|
||||
|
||||
controllerContext.RequestContext.RouteData.DataTokens.Add("area", areaName);
|
||||
|
||||
return controllerContext;
|
||||
}
|
||||
|
||||
private class TestableRemoteAttribute : RemoteAttribute
|
||||
{
|
||||
public RouteCollection RouteTable = new RouteCollection();
|
||||
|
||||
public TestableRemoteAttribute(string action, string controller, AreaReference areaReference)
|
||||
: base(action, controller, areaReference)
|
||||
{
|
||||
}
|
||||
|
||||
public TestableRemoteAttribute(string action, string controller, string areaName)
|
||||
: base(action, controller, areaName)
|
||||
{
|
||||
}
|
||||
|
||||
public TestableRemoteAttribute(string action, string controller)
|
||||
: base(action, controller)
|
||||
{
|
||||
}
|
||||
|
||||
public TestableRemoteAttribute(string routeName)
|
||||
: base(routeName)
|
||||
{
|
||||
}
|
||||
|
||||
protected override RouteCollection Routes
|
||||
{
|
||||
get { return RouteTable; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue