PageRenderTime 47ms CodeModel.GetById 1ms RepoModel.GetById 1ms app.codeStats 0ms

/test/System.Web.Mvc.Test/Test/DataAnnotationsModelValidatorProviderTest.cs

https://bitbucket.org/mdavid/aspnetwebstack
C# | 725 lines | 510 code | 124 blank | 91 comment | 4 complexity | ea13fa4d9a62af37c4a24b8e1ac8a78f MD5 | raw file
  1. using System.Collections.Generic;
  2. using System.ComponentModel.DataAnnotations;
  3. using System.Linq;
  4. using Moq;
  5. using Xunit;
  6. using Assert = Microsoft.TestCommon.AssertEx;
  7. namespace System.Web.Mvc.Test
  8. {
  9. public class DataAnnotationsModelValidatorProviderTest
  10. {
  11. // Validation attribute adapter registration
  12. private class MyValidationAttribute : ValidationAttribute
  13. {
  14. public override bool IsValid(object value)
  15. {
  16. throw new NotImplementedException();
  17. }
  18. }
  19. private class MyValidationAttributeAdapter : DataAnnotationsModelValidator<MyValidationAttribute>
  20. {
  21. public MyValidationAttributeAdapter(ModelMetadata metadata, ControllerContext context, MyValidationAttribute attribute)
  22. : base(metadata, context, attribute)
  23. {
  24. }
  25. }
  26. private class MyValidationAttributeAdapterBadCtor : ModelValidator
  27. {
  28. public MyValidationAttributeAdapterBadCtor(ModelMetadata metadata, ControllerContext context)
  29. : base(metadata, context)
  30. {
  31. }
  32. public override IEnumerable<ModelValidationResult> Validate(object container)
  33. {
  34. throw new NotImplementedException();
  35. }
  36. }
  37. private class MyDefaultValidationAttributeAdapter : DataAnnotationsModelValidator
  38. {
  39. public MyDefaultValidationAttributeAdapter(ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute)
  40. : base(metadata, context, attribute)
  41. {
  42. }
  43. }
  44. [MyValidation]
  45. private class MyValidatedClass
  46. {
  47. }
  48. [Fact]
  49. public void RegisterAdapter()
  50. {
  51. var oldFactories = DataAnnotationsModelValidatorProvider.AttributeFactories;
  52. try
  53. {
  54. // Arrange
  55. DataAnnotationsModelValidatorProvider.AttributeFactories = new Dictionary<Type, DataAnnotationsModelValidationFactory>();
  56. // Act
  57. DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(MyValidationAttribute), typeof(MyValidationAttributeAdapter));
  58. // Assert
  59. var type = DataAnnotationsModelValidatorProvider.AttributeFactories.Keys.Single();
  60. Assert.Equal(typeof(MyValidationAttribute), type);
  61. var factory = DataAnnotationsModelValidatorProvider.AttributeFactories.Values.Single();
  62. var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => null, typeof(object));
  63. var context = new ControllerContext();
  64. var attribute = new MyValidationAttribute();
  65. var validator = factory(metadata, context, attribute);
  66. Assert.IsType<MyValidationAttributeAdapter>(validator);
  67. }
  68. finally
  69. {
  70. DataAnnotationsModelValidatorProvider.AttributeFactories = oldFactories;
  71. }
  72. }
  73. [Fact]
  74. public void RegisterAdapterGuardClauses()
  75. {
  76. // Attribute type cannot be null
  77. Assert.ThrowsArgumentNull(
  78. () => DataAnnotationsModelValidatorProvider.RegisterAdapter(null, typeof(MyValidationAttributeAdapter)),
  79. "attributeType");
  80. // Adapter type cannot be null
  81. Assert.ThrowsArgumentNull(
  82. () => DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(MyValidationAttribute), null),
  83. "adapterType");
  84. // Validation attribute must derive from ValidationAttribute
  85. Assert.Throws<ArgumentException>(
  86. () => DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(object), typeof(MyValidationAttributeAdapter)),
  87. "The type System.Object must derive from System.ComponentModel.DataAnnotations.ValidationAttribute\r\nParameter name: attributeType");
  88. // Adapter must derive from ModelValidator
  89. Assert.Throws<ArgumentException>(
  90. () => DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(MyValidationAttribute), typeof(object)),
  91. "The type System.Object must derive from System.Web.Mvc.ModelValidator\r\nParameter name: adapterType");
  92. // Adapter must have the expected constructor
  93. Assert.Throws<ArgumentException>(
  94. () => DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(MyValidationAttribute), typeof(MyValidationAttributeAdapterBadCtor)),
  95. "The type System.Web.Mvc.Test.DataAnnotationsModelValidatorProviderTest+MyValidationAttributeAdapterBadCtor must have a public constructor which accepts three parameters of types System.Web.Mvc.ModelMetadata, System.Web.Mvc.ControllerContext, and System.Web.Mvc.Test.DataAnnotationsModelValidatorProviderTest+MyValidationAttribute\r\nParameter name: adapterType");
  96. }
  97. [Fact]
  98. public void RegisterAdapterFactory()
  99. {
  100. var oldFactories = DataAnnotationsModelValidatorProvider.AttributeFactories;
  101. try
  102. {
  103. // Arrange
  104. DataAnnotationsModelValidatorProvider.AttributeFactories = new Dictionary<Type, DataAnnotationsModelValidationFactory>();
  105. DataAnnotationsModelValidationFactory factory = delegate { return null; };
  106. // Act
  107. DataAnnotationsModelValidatorProvider.RegisterAdapterFactory(typeof(MyValidationAttribute), factory);
  108. // Assert
  109. var type = DataAnnotationsModelValidatorProvider.AttributeFactories.Keys.Single();
  110. Assert.Equal(typeof(MyValidationAttribute), type);
  111. Assert.Same(factory, DataAnnotationsModelValidatorProvider.AttributeFactories.Values.Single());
  112. }
  113. finally
  114. {
  115. DataAnnotationsModelValidatorProvider.AttributeFactories = oldFactories;
  116. }
  117. }
  118. [Fact]
  119. public void RegisterAdapterFactoryGuardClauses()
  120. {
  121. DataAnnotationsModelValidationFactory factory = (metadata, context, attribute) => null;
  122. // Attribute type cannot be null
  123. Assert.ThrowsArgumentNull(
  124. () => DataAnnotationsModelValidatorProvider.RegisterAdapterFactory(null, factory),
  125. "attributeType");
  126. // Factory cannot be null
  127. Assert.ThrowsArgumentNull(
  128. () => DataAnnotationsModelValidatorProvider.RegisterAdapterFactory(typeof(MyValidationAttribute), null),
  129. "factory");
  130. // Validation attribute must derive from ValidationAttribute
  131. Assert.Throws<ArgumentException>(
  132. () => DataAnnotationsModelValidatorProvider.RegisterAdapterFactory(typeof(object), factory),
  133. "The type System.Object must derive from System.ComponentModel.DataAnnotations.ValidationAttribute\r\nParameter name: attributeType");
  134. }
  135. [Fact]
  136. public void RegisterDefaultAdapter()
  137. {
  138. var oldFactory = DataAnnotationsModelValidatorProvider.DefaultAttributeFactory;
  139. try
  140. {
  141. // Arrange
  142. var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => null, typeof(MyValidatedClass));
  143. var context = new ControllerContext();
  144. DataAnnotationsModelValidatorProvider.RegisterDefaultAdapter(typeof(MyDefaultValidationAttributeAdapter));
  145. // Act
  146. var result = new DataAnnotationsModelValidatorProvider().GetValidators(metadata, context).Single();
  147. // Assert
  148. Assert.IsType<MyDefaultValidationAttributeAdapter>(result);
  149. }
  150. finally
  151. {
  152. DataAnnotationsModelValidatorProvider.DefaultAttributeFactory = oldFactory;
  153. }
  154. }
  155. [Fact]
  156. public void RegisterDefaultAdapterGuardClauses()
  157. {
  158. // Adapter type cannot be null
  159. Assert.ThrowsArgumentNull(
  160. () => DataAnnotationsModelValidatorProvider.RegisterDefaultAdapter(null),
  161. "adapterType");
  162. // Adapter must derive from ModelValidator
  163. Assert.Throws<ArgumentException>(
  164. () => DataAnnotationsModelValidatorProvider.RegisterDefaultAdapter(typeof(object)),
  165. "The type System.Object must derive from System.Web.Mvc.ModelValidator\r\nParameter name: adapterType");
  166. // Adapter must have the expected constructor
  167. Assert.Throws<ArgumentException>(
  168. () => DataAnnotationsModelValidatorProvider.RegisterDefaultAdapter(typeof(MyValidationAttributeAdapterBadCtor)),
  169. "The type System.Web.Mvc.Test.DataAnnotationsModelValidatorProviderTest+MyValidationAttributeAdapterBadCtor must have a public constructor which accepts three parameters of types System.Web.Mvc.ModelMetadata, System.Web.Mvc.ControllerContext, and System.ComponentModel.DataAnnotations.ValidationAttribute\r\nParameter name: adapterType");
  170. }
  171. [Fact]
  172. public void RegisterDefaultAdapterFactory()
  173. {
  174. var oldFactory = DataAnnotationsModelValidatorProvider.DefaultAttributeFactory;
  175. try
  176. {
  177. // Arrange
  178. var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => null, typeof(MyValidatedClass));
  179. var context = new ControllerContext();
  180. ModelValidator validator = new Mock<ModelValidator>(metadata, context).Object;
  181. DataAnnotationsModelValidationFactory factory = delegate { return validator; };
  182. DataAnnotationsModelValidatorProvider.RegisterDefaultAdapterFactory(factory);
  183. // Act
  184. var result = new DataAnnotationsModelValidatorProvider().GetValidators(metadata, context).Single();
  185. // Assert
  186. Assert.Same(validator, result);
  187. }
  188. finally
  189. {
  190. DataAnnotationsModelValidatorProvider.DefaultAttributeFactory = oldFactory;
  191. }
  192. }
  193. [Fact]
  194. public void RegisterDefaultAdapterFactoryGuardClauses()
  195. {
  196. // Factory cannot be null
  197. Assert.ThrowsArgumentNull(
  198. () => DataAnnotationsModelValidatorProvider.RegisterDefaultAdapterFactory(null),
  199. "factory");
  200. }
  201. // IValidatableObject adapter registration
  202. private class MyValidatableAdapter : ModelValidator
  203. {
  204. public MyValidatableAdapter(ModelMetadata metadata, ControllerContext context)
  205. : base(metadata, context)
  206. {
  207. }
  208. public override IEnumerable<ModelValidationResult> Validate(object container)
  209. {
  210. throw new NotImplementedException();
  211. }
  212. }
  213. private class MyValidatableAdapterBadCtor : ModelValidator
  214. {
  215. public MyValidatableAdapterBadCtor(ModelMetadata metadata, ControllerContext context, int unused)
  216. : base(metadata, context)
  217. {
  218. }
  219. public override IEnumerable<ModelValidationResult> Validate(object container)
  220. {
  221. throw new NotImplementedException();
  222. }
  223. }
  224. private class MyValidatableClass : IValidatableObject
  225. {
  226. public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
  227. {
  228. throw new NotImplementedException();
  229. }
  230. }
  231. [Fact]
  232. public void RegisterValidatableObjectAdapter()
  233. {
  234. var oldFactories = DataAnnotationsModelValidatorProvider.ValidatableFactories;
  235. try
  236. {
  237. // Arrange
  238. DataAnnotationsModelValidatorProvider.ValidatableFactories = new Dictionary<Type, DataAnnotationsValidatableObjectAdapterFactory>();
  239. IValidatableObject validatable = new Mock<IValidatableObject>().Object;
  240. // Act
  241. DataAnnotationsModelValidatorProvider.RegisterValidatableObjectAdapter(validatable.GetType(), typeof(MyValidatableAdapter));
  242. // Assert
  243. var type = DataAnnotationsModelValidatorProvider.ValidatableFactories.Keys.Single();
  244. Assert.Equal(validatable.GetType(), type);
  245. var factory = DataAnnotationsModelValidatorProvider.ValidatableFactories.Values.Single();
  246. var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => null, typeof(object));
  247. var context = new ControllerContext();
  248. var validator = factory(metadata, context);
  249. Assert.IsType<MyValidatableAdapter>(validator);
  250. }
  251. finally
  252. {
  253. DataAnnotationsModelValidatorProvider.ValidatableFactories = oldFactories;
  254. }
  255. }
  256. [Fact]
  257. public void RegisterValidatableObjectAdapterGuardClauses()
  258. {
  259. // Attribute type cannot be null
  260. Assert.ThrowsArgumentNull(
  261. () => DataAnnotationsModelValidatorProvider.RegisterValidatableObjectAdapter(null, typeof(MyValidatableAdapter)),
  262. "modelType");
  263. // Adapter type cannot be null
  264. Assert.ThrowsArgumentNull(
  265. () => DataAnnotationsModelValidatorProvider.RegisterValidatableObjectAdapter(typeof(MyValidatableClass), null),
  266. "adapterType");
  267. // Validation attribute must derive from ValidationAttribute
  268. Assert.Throws<ArgumentException>(
  269. () => DataAnnotationsModelValidatorProvider.RegisterValidatableObjectAdapter(typeof(object), typeof(MyValidatableAdapter)),
  270. "The type System.Object must derive from System.ComponentModel.DataAnnotations.IValidatableObject\r\nParameter name: modelType");
  271. // Adapter must derive from ModelValidator
  272. Assert.Throws<ArgumentException>(
  273. () => DataAnnotationsModelValidatorProvider.RegisterValidatableObjectAdapter(typeof(MyValidatableClass), typeof(object)),
  274. "The type System.Object must derive from System.Web.Mvc.ModelValidator\r\nParameter name: adapterType");
  275. // Adapter must have the expected constructor
  276. Assert.Throws<ArgumentException>(
  277. () => DataAnnotationsModelValidatorProvider.RegisterValidatableObjectAdapter(typeof(MyValidatableClass), typeof(MyValidatableAdapterBadCtor)),
  278. "The type System.Web.Mvc.Test.DataAnnotationsModelValidatorProviderTest+MyValidatableAdapterBadCtor must have a public constructor which accepts two parameters of types System.Web.Mvc.ModelMetadata and System.Web.Mvc.ControllerContext.\r\nParameter name: adapterType");
  279. }
  280. [Fact]
  281. public void RegisterValidatableObjectAdapterFactory()
  282. {
  283. var oldFactories = DataAnnotationsModelValidatorProvider.ValidatableFactories;
  284. try
  285. {
  286. // Arrange
  287. DataAnnotationsModelValidatorProvider.ValidatableFactories = new Dictionary<Type, DataAnnotationsValidatableObjectAdapterFactory>();
  288. DataAnnotationsValidatableObjectAdapterFactory factory = delegate { return null; };
  289. // Act
  290. DataAnnotationsModelValidatorProvider.RegisterValidatableObjectAdapterFactory(typeof(MyValidatableClass), factory);
  291. // Assert
  292. var type = DataAnnotationsModelValidatorProvider.ValidatableFactories.Keys.Single();
  293. Assert.Equal(typeof(MyValidatableClass), type);
  294. Assert.Same(factory, DataAnnotationsModelValidatorProvider.ValidatableFactories.Values.Single());
  295. }
  296. finally
  297. {
  298. DataAnnotationsModelValidatorProvider.ValidatableFactories = oldFactories;
  299. }
  300. }
  301. [Fact]
  302. public void RegisterValidatableObjectAdapterFactoryGuardClauses()
  303. {
  304. DataAnnotationsValidatableObjectAdapterFactory factory = (metadata, context) => null;
  305. // Attribute type cannot be null
  306. Assert.ThrowsArgumentNull(
  307. () => DataAnnotationsModelValidatorProvider.RegisterValidatableObjectAdapterFactory(null, factory),
  308. "modelType");
  309. // Factory cannot be null
  310. Assert.ThrowsArgumentNull(
  311. () => DataAnnotationsModelValidatorProvider.RegisterValidatableObjectAdapterFactory(typeof(MyValidatableClass), null),
  312. "factory");
  313. // Validation attribute must derive from ValidationAttribute
  314. Assert.Throws<ArgumentException>(
  315. () => DataAnnotationsModelValidatorProvider.RegisterValidatableObjectAdapterFactory(typeof(object), factory),
  316. "The type System.Object must derive from System.ComponentModel.DataAnnotations.IValidatableObject\r\nParameter name: modelType");
  317. }
  318. [Fact]
  319. public void RegisterDefaultValidatableObjectAdapter()
  320. {
  321. var oldFactory = DataAnnotationsModelValidatorProvider.DefaultValidatableFactory;
  322. try
  323. {
  324. // Arrange
  325. var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => null, typeof(MyValidatableClass));
  326. var context = new ControllerContext();
  327. DataAnnotationsModelValidatorProvider.RegisterDefaultValidatableObjectAdapter(typeof(MyValidatableAdapter));
  328. // Act
  329. var result = new DataAnnotationsModelValidatorProvider().GetValidators(metadata, context).Single();
  330. // Assert
  331. Assert.IsType<MyValidatableAdapter>(result);
  332. }
  333. finally
  334. {
  335. DataAnnotationsModelValidatorProvider.DefaultValidatableFactory = oldFactory;
  336. }
  337. }
  338. [Fact]
  339. public void RegisterDefaultValidatableObjectAdapterGuardClauses()
  340. {
  341. // Adapter type cannot be null
  342. Assert.ThrowsArgumentNull(
  343. () => DataAnnotationsModelValidatorProvider.RegisterDefaultValidatableObjectAdapter(null),
  344. "adapterType");
  345. // Adapter must derive from ModelValidator
  346. Assert.Throws<ArgumentException>(
  347. () => DataAnnotationsModelValidatorProvider.RegisterDefaultValidatableObjectAdapter(typeof(object)),
  348. "The type System.Object must derive from System.Web.Mvc.ModelValidator\r\nParameter name: adapterType");
  349. // Adapter must have the expected constructor
  350. Assert.Throws<ArgumentException>(
  351. () => DataAnnotationsModelValidatorProvider.RegisterDefaultValidatableObjectAdapter(typeof(MyValidatableAdapterBadCtor)),
  352. "The type System.Web.Mvc.Test.DataAnnotationsModelValidatorProviderTest+MyValidatableAdapterBadCtor must have a public constructor which accepts two parameters of types System.Web.Mvc.ModelMetadata and System.Web.Mvc.ControllerContext.\r\nParameter name: adapterType");
  353. }
  354. [Fact]
  355. public void RegisterDefaultValidatableObjectAdapterFactory()
  356. {
  357. var oldFactory = DataAnnotationsModelValidatorProvider.DefaultValidatableFactory;
  358. try
  359. {
  360. // Arrange
  361. var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => null, typeof(MyValidatableClass));
  362. var context = new ControllerContext();
  363. ModelValidator validator = new Mock<ModelValidator>(metadata, context).Object;
  364. DataAnnotationsValidatableObjectAdapterFactory factory = delegate { return validator; };
  365. DataAnnotationsModelValidatorProvider.RegisterDefaultValidatableObjectAdapterFactory(factory);
  366. // Act
  367. var result = new DataAnnotationsModelValidatorProvider().GetValidators(metadata, context).Single();
  368. // Assert
  369. Assert.Same(validator, result);
  370. }
  371. finally
  372. {
  373. DataAnnotationsModelValidatorProvider.DefaultValidatableFactory = oldFactory;
  374. }
  375. }
  376. [Fact]
  377. public void RegisterDefaultValidatableObjectAdapterFactoryGuardClauses()
  378. {
  379. // Factory cannot be null
  380. Assert.ThrowsArgumentNull(
  381. () => DataAnnotationsModelValidatorProvider.RegisterDefaultValidatableObjectAdapterFactory(null),
  382. "factory");
  383. }
  384. // Pre-configured adapters
  385. [Fact]
  386. public void AdapterForRangeAttributeRegistered()
  387. {
  388. // Arrange
  389. var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => null, typeof(object));
  390. var context = new ControllerContext();
  391. var adapters = DataAnnotationsModelValidatorProvider.AttributeFactories;
  392. var adapterFactory = adapters.Single(kvp => kvp.Key == typeof(RangeAttribute)).Value;
  393. // Act
  394. var adapter = adapterFactory(metadata, context, new RangeAttribute(1, 100));
  395. // Assert
  396. Assert.IsType<RangeAttributeAdapter>(adapter);
  397. }
  398. [Fact]
  399. public void AdapterForRegularExpressionAttributeRegistered()
  400. {
  401. // Arrange
  402. var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => null, typeof(object));
  403. var context = new ControllerContext();
  404. var adapters = DataAnnotationsModelValidatorProvider.AttributeFactories;
  405. var adapterFactory = adapters.Single(kvp => kvp.Key == typeof(RegularExpressionAttribute)).Value;
  406. // Act
  407. var adapter = adapterFactory(metadata, context, new RegularExpressionAttribute("abc"));
  408. // Assert
  409. Assert.IsType<RegularExpressionAttributeAdapter>(adapter);
  410. }
  411. [Fact]
  412. public void AdapterForRequiredAttributeRegistered()
  413. {
  414. // Arrange
  415. var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => null, typeof(object));
  416. var context = new ControllerContext();
  417. var adapters = DataAnnotationsModelValidatorProvider.AttributeFactories;
  418. var adapterFactory = adapters.Single(kvp => kvp.Key == typeof(RequiredAttribute)).Value;
  419. // Act
  420. var adapter = adapterFactory(metadata, context, new RequiredAttribute());
  421. // Assert
  422. Assert.IsType<RequiredAttributeAdapter>(adapter);
  423. }
  424. [Fact]
  425. public void AdapterForStringLengthAttributeRegistered()
  426. {
  427. // Arrange
  428. var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => null, typeof(object));
  429. var context = new ControllerContext();
  430. var adapters = DataAnnotationsModelValidatorProvider.AttributeFactories;
  431. var adapterFactory = adapters.Single(kvp => kvp.Key == typeof(StringLengthAttribute)).Value;
  432. // Act
  433. var adapter = adapterFactory(metadata, context, new StringLengthAttribute(6));
  434. // Assert
  435. Assert.IsType<StringLengthAttributeAdapter>(adapter);
  436. }
  437. // Default adapter factory for unknown attribute type
  438. [Fact]
  439. public void UnknownValidationAttributeGetsDefaultAdapter()
  440. {
  441. // Arrange
  442. var provider = new DataAnnotationsModelValidatorProvider();
  443. var context = new ControllerContext();
  444. var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => null, typeof(DummyClassWithDummyValidationAttribute));
  445. // Act
  446. IEnumerable<ModelValidator> validators = provider.GetValidators(metadata, context);
  447. // Assert
  448. var validator = validators.Single();
  449. Assert.IsType<DataAnnotationsModelValidator>(validator);
  450. }
  451. private class DummyValidationAttribute : ValidationAttribute
  452. {
  453. }
  454. [DummyValidation]
  455. private class DummyClassWithDummyValidationAttribute
  456. {
  457. }
  458. // Default IValidatableObject adapter factory
  459. [Fact]
  460. public void IValidatableObjectGetsAValidator()
  461. {
  462. // Arrange
  463. var provider = new DataAnnotationsModelValidatorProvider();
  464. var mockValidatable = new Mock<IValidatableObject>();
  465. var context = new ControllerContext();
  466. var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => null, mockValidatable.Object.GetType());
  467. // Act
  468. IEnumerable<ModelValidator> validators = provider.GetValidators(metadata, context);
  469. // Assert
  470. Assert.Single(validators);
  471. }
  472. // Implicit [Required] attribute
  473. [Fact]
  474. public void ReferenceTypesDontGetImplicitRequiredAttribute()
  475. {
  476. // Arrange
  477. var provider = new DataAnnotationsModelValidatorProvider();
  478. var context = new ControllerContext();
  479. var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => null, typeof(string));
  480. // Act
  481. IEnumerable<ModelValidator> validators = provider.GetValidators(metadata, context);
  482. // Assert
  483. Assert.Empty(validators);
  484. }
  485. [Fact]
  486. public void NonNullableValueTypesGetImplicitRequiredAttribute()
  487. {
  488. // Arrange
  489. var provider = new DataAnnotationsModelValidatorProvider();
  490. var context = new ControllerContext();
  491. var metadata = ModelMetadataProviders.Current.GetMetadataForProperty(() => null, typeof(DummyRequiredAttributeHelperClass), "WithoutAttribute");
  492. // Act
  493. IEnumerable<ModelValidator> validators = provider.GetValidators(metadata, context);
  494. // Assert
  495. ModelValidator validator = validators.Single();
  496. ModelClientValidationRule rule = validator.GetClientValidationRules().Single();
  497. Assert.IsType<ModelClientValidationRequiredRule>(rule);
  498. }
  499. [Fact]
  500. public void NonNullableValueTypesWithExplicitRequiredAttributeDoesntGetImplictRequiredAttribute()
  501. {
  502. // Arrange
  503. var provider = new DataAnnotationsModelValidatorProvider();
  504. var context = new ControllerContext();
  505. var metadata = ModelMetadataProviders.Current.GetMetadataForProperty(() => null, typeof(DummyRequiredAttributeHelperClass), "WithAttribute");
  506. // Act
  507. IEnumerable<ModelValidator> validators = provider.GetValidators(metadata, context);
  508. // Assert
  509. ModelValidator validator = validators.Single();
  510. ModelClientValidationRule rule = validator.GetClientValidationRules().Single();
  511. Assert.IsType<ModelClientValidationRequiredRule>(rule);
  512. Assert.Equal("Custom Required Message", rule.ErrorMessage);
  513. }
  514. [Fact]
  515. public void NonNullableValueTypeDoesntGetImplicitRequiredAttributeWhenFlagIsOff()
  516. {
  517. DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
  518. try
  519. {
  520. // Arrange
  521. var provider = new DataAnnotationsModelValidatorProvider();
  522. var context = new ControllerContext();
  523. var metadata = ModelMetadataProviders.Current.GetMetadataForProperty(() => null, typeof(DummyRequiredAttributeHelperClass), "WithoutAttribute");
  524. // Act
  525. IEnumerable<ModelValidator> validators = provider.GetValidators(metadata, context);
  526. // Assert
  527. Assert.Empty(validators);
  528. }
  529. finally
  530. {
  531. DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = true;
  532. }
  533. }
  534. private class DummyRequiredAttributeHelperClass
  535. {
  536. [Required(ErrorMessage = "Custom Required Message")]
  537. public int WithAttribute { get; set; }
  538. public int WithoutAttribute { get; set; }
  539. }
  540. // Integration with metadata system
  541. [Fact]
  542. public void DoesNotReadPropertyValue()
  543. {
  544. // Arrange
  545. ObservableModel model = new ObservableModel();
  546. ModelMetadata metadata = new DataAnnotationsModelMetadataProvider().GetMetadataForProperty(() => model.TheProperty, typeof(ObservableModel), "TheProperty");
  547. ControllerContext controllerContext = new ControllerContext();
  548. // Act
  549. ModelValidator[] validators = new DataAnnotationsModelValidatorProvider().GetValidators(metadata, controllerContext).ToArray();
  550. ModelValidationResult[] results = validators.SelectMany(o => o.Validate(model)).ToArray();
  551. // Assert
  552. Assert.Empty(validators);
  553. Assert.False(model.PropertyWasRead());
  554. }
  555. private class ObservableModel
  556. {
  557. private bool _propertyWasRead;
  558. public string TheProperty
  559. {
  560. get
  561. {
  562. _propertyWasRead = true;
  563. return "Hello";
  564. }
  565. }
  566. public bool PropertyWasRead()
  567. {
  568. return _propertyWasRead;
  569. }
  570. }
  571. private class BaseModel
  572. {
  573. public virtual string MyProperty { get; set; }
  574. }
  575. private class DerivedModel : BaseModel
  576. {
  577. [StringLength(10)]
  578. public override string MyProperty
  579. {
  580. get { return base.MyProperty; }
  581. set { base.MyProperty = value; }
  582. }
  583. }
  584. [Fact]
  585. public void GetValidatorsReturnsClientValidatorForDerivedTypeAppliedAgainstBaseTypeViaFromLambdaExpression()
  586. { // Dev10 Bug #868619
  587. // Arrange
  588. var provider = new DataAnnotationsModelValidatorProvider();
  589. var context = new ControllerContext();
  590. var viewdata = new ViewDataDictionary<DerivedModel>();
  591. var metadata = ModelMetadata.FromLambdaExpression(m => m.MyProperty, viewdata); // Bug is in FromLambdaExpression
  592. // Act
  593. IEnumerable<ModelValidator> validators = provider.GetValidators(metadata, context);
  594. // Assert
  595. ModelValidator validator = validators.Single();
  596. ModelClientValidationRule clientRule = validator.GetClientValidationRules().Single();
  597. Assert.IsType<ModelClientValidationStringLengthRule>(clientRule);
  598. Assert.Equal(10, clientRule.ValidationParameters["max"]);
  599. }
  600. }
  601. }