PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/mvc3/test/MvcFuturesTest/Mvc/ModelBinding/Test/ModelBinderProviderCollectionTest.cs

https://github.com/jeanlyn/ASP.NET-Mvc-3
C# | 483 lines | 331 code | 91 blank | 61 comment | 0 complexity | c2f5cf8836caab1fefb8ed0e7272903c MD5 | raw file
  1. namespace Microsoft.Web.Mvc.ModelBinding.Test {
  2. using System;
  3. using System.Collections.Generic;
  4. using System.ComponentModel.DataAnnotations;
  5. using System.Linq;
  6. using System.Web.Mvc;
  7. using System.Web.TestUtil;
  8. using Microsoft.VisualStudio.TestTools.UnitTesting;
  9. using Microsoft.Web.UnitTestUtil;
  10. using Moq;
  11. using ModelBinderProviderCollection = Microsoft.Web.Mvc.ModelBinding.ModelBinderProviderCollection;
  12. [TestClass]
  13. public class ModelBinderProviderCollectionTest {
  14. [TestMethod]
  15. public void ListWrappingConstructor() {
  16. // Arrange
  17. ModelBinderProvider[] providers = new ModelBinderProvider[] {
  18. new Mock<ModelBinderProvider>().Object,
  19. new Mock<ModelBinderProvider>().Object
  20. };
  21. // Act
  22. ModelBinderProviderCollection collection = new ModelBinderProviderCollection(providers);
  23. // Assert
  24. CollectionAssert.AreEqual(providers, collection);
  25. }
  26. [TestMethod]
  27. public void DefaultConstructor() {
  28. // Act
  29. ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
  30. // Assert
  31. Assert.AreEqual(0, collection.Count);
  32. }
  33. [TestMethod]
  34. public void AddNullProviderThrows() {
  35. // Arrange
  36. ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
  37. // Act & Assert
  38. ExceptionHelper.ExpectArgumentNullException(
  39. delegate {
  40. collection.Add(null);
  41. },
  42. "item");
  43. }
  44. [TestMethod]
  45. public void RegisterBinderForGenericType_Factory() {
  46. // Arrange
  47. ModelBinderProvider mockProvider = new Mock<ModelBinderProvider>().Object;
  48. IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
  49. ModelBinderProviderCollection collection = new ModelBinderProviderCollection() {
  50. mockProvider
  51. };
  52. // Act
  53. collection.RegisterBinderForGenericType(typeof(List<>), _ => mockBinder);
  54. // Assert
  55. GenericModelBinderProvider genericProvider = collection[0] as GenericModelBinderProvider;
  56. Assert.IsNotNull(genericProvider, "Generic provider should've been inserted at the front of the list.");
  57. Assert.AreEqual(typeof(List<>), genericProvider.ModelType);
  58. Assert.AreEqual(mockProvider, collection[1]);
  59. }
  60. [TestMethod]
  61. public void RegisterBinderForGenericType_Instance() {
  62. // Arrange
  63. ModelBinderProvider mockProvider = new Mock<ModelBinderProvider>().Object;
  64. IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
  65. ModelBinderProviderCollection collection = new ModelBinderProviderCollection() {
  66. mockProvider
  67. };
  68. // Act
  69. collection.RegisterBinderForGenericType(typeof(List<>), mockBinder);
  70. // Assert
  71. GenericModelBinderProvider genericProvider = collection[0] as GenericModelBinderProvider;
  72. Assert.IsNotNull(genericProvider, "Generic provider should've been inserted at the front of the list.");
  73. Assert.AreEqual(typeof(List<>), genericProvider.ModelType);
  74. Assert.AreEqual(mockProvider, collection[1]);
  75. }
  76. [TestMethod]
  77. public void RegisterBinderForGenericType_Type() {
  78. // Arrange
  79. ModelBinderProvider mockProvider = new Mock<ModelBinderProvider>().Object;
  80. IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
  81. ModelBinderProviderCollection collection = new ModelBinderProviderCollection() {
  82. mockProvider
  83. };
  84. // Act
  85. collection.RegisterBinderForGenericType(typeof(List<>), typeof(CollectionModelBinder<>));
  86. // Assert
  87. GenericModelBinderProvider genericProvider = collection[0] as GenericModelBinderProvider;
  88. Assert.IsNotNull(genericProvider, "Generic provider should've been inserted at the front of the list.");
  89. Assert.AreEqual(typeof(List<>), genericProvider.ModelType);
  90. Assert.AreEqual(mockProvider, collection[1]);
  91. }
  92. [TestMethod]
  93. public void RegisterBinderForType_Factory() {
  94. // Arrange
  95. ModelBinderProvider mockProvider = new Mock<ModelBinderProvider>().Object;
  96. IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
  97. ModelBinderProviderCollection collection = new ModelBinderProviderCollection() {
  98. mockProvider
  99. };
  100. // Act
  101. collection.RegisterBinderForType(typeof(int), () => mockBinder);
  102. // Assert
  103. SimpleModelBinderProvider simpleProvider = collection[0] as SimpleModelBinderProvider;
  104. Assert.IsNotNull(simpleProvider, "Simple provider should've been inserted at the front of the list.");
  105. Assert.AreEqual(typeof(int), simpleProvider.ModelType);
  106. Assert.AreEqual(mockProvider, collection[1]);
  107. }
  108. [TestMethod]
  109. public void RegisterBinderForType_Instance() {
  110. // Arrange
  111. ModelBinderProvider mockProvider = new Mock<ModelBinderProvider>().Object;
  112. IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
  113. ModelBinderProviderCollection collection = new ModelBinderProviderCollection() {
  114. mockProvider
  115. };
  116. // Act
  117. collection.RegisterBinderForType(typeof(int), mockBinder);
  118. // Assert
  119. SimpleModelBinderProvider simpleProvider = collection[0] as SimpleModelBinderProvider;
  120. Assert.IsNotNull(simpleProvider, "Simple provider should've been inserted at the front of the list.");
  121. Assert.AreEqual(typeof(int), simpleProvider.ModelType);
  122. Assert.AreEqual(mockProvider, collection[1]);
  123. }
  124. [TestMethod]
  125. public void RegisterBinderForType_Instance_InsertsNewProviderBehindFrontOfListProviders() {
  126. // Arrange
  127. ModelBinderProvider frontOfListProvider = new ProviderAtFront();
  128. IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
  129. ModelBinderProviderCollection collection = new ModelBinderProviderCollection() {
  130. frontOfListProvider
  131. };
  132. // Act
  133. collection.RegisterBinderForType(typeof(int), mockBinder);
  134. // Assert
  135. CollectionAssert.AreEqual(
  136. new Type[] { typeof(ProviderAtFront), typeof(SimpleModelBinderProvider) },
  137. collection.Select(o => o.GetType()).ToArray(),
  138. "New provider should be inserted after any marked 'front of list'.");
  139. }
  140. [TestMethod]
  141. public void SetItem() {
  142. // Arrange
  143. ModelBinderProvider provider0 = new Mock<ModelBinderProvider>().Object;
  144. ModelBinderProvider provider1 = new Mock<ModelBinderProvider>().Object;
  145. ModelBinderProvider provider2 = new Mock<ModelBinderProvider>().Object;
  146. ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
  147. collection.Add(provider0);
  148. collection.Add(provider1);
  149. // Act
  150. collection[1] = provider2;
  151. // Assert
  152. CollectionAssert.AreEqual(new ModelBinderProvider[] { provider0, provider2 }, collection);
  153. }
  154. [TestMethod]
  155. public void SetNullProviderThrows() {
  156. // Arrange
  157. ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
  158. collection.Add(new Mock<ModelBinderProvider>().Object);
  159. // Act & Assert
  160. ExceptionHelper.ExpectArgumentNullException(
  161. delegate {
  162. collection[0] = null;
  163. },
  164. "item");
  165. }
  166. [TestMethod]
  167. public void GetBinder_FromAttribute_BadAttribute_Throws() {
  168. // Arrange
  169. ControllerContext controllerContext = new ControllerContext();
  170. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext() {
  171. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_BadAttribute))
  172. };
  173. ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
  174. // Act & assert
  175. ExceptionHelper.ExpectInvalidOperationException(
  176. delegate {
  177. providers.GetBinder(controllerContext, bindingContext);
  178. },
  179. @"The type 'System.Object' does not subclass Microsoft.Web.Mvc.ModelBinding.ModelBinderProvider or implement the interface Microsoft.Web.Mvc.ModelBinding.IExtensibleModelBinder.");
  180. }
  181. [TestMethod]
  182. public void GetBinder_FromAttribute_Binder_Generic_ReturnsBinder() {
  183. // Arrange
  184. ControllerContext controllerContext = new ControllerContext();
  185. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext() {
  186. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_Binder_Generic<int>)),
  187. ModelName = "foo",
  188. ValueProvider = new SimpleValueProvider() {
  189. { "foo", "fooValue" }
  190. }
  191. };
  192. ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
  193. providers.RegisterBinderForType(typeof(ModelWithProviderAttribute_Binder_Generic<int>), new Mock<IExtensibleModelBinder>().Object, true /* suppressPrefix */);
  194. // Act
  195. IExtensibleModelBinder binder = providers.GetBinder(controllerContext, bindingContext);
  196. // Assert
  197. Assert.AreEqual(typeof(CustomGenericBinder<int>), binder.GetType(), "Binder should've come from attribute rather than collection.");
  198. }
  199. [TestMethod]
  200. public void GetBinder_FromAttribute_Binder_SuppressPrefixCheck_ReturnsBinder() {
  201. // Arrange
  202. ControllerContext controllerContext = new ControllerContext();
  203. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext() {
  204. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_Binder_SuppressPrefix)),
  205. ModelName = "foo",
  206. ValueProvider = new SimpleValueProvider() {
  207. { "bar", "barValue" }
  208. }
  209. };
  210. ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
  211. providers.RegisterBinderForType(typeof(ModelWithProviderAttribute_Binder_SuppressPrefix), new Mock<IExtensibleModelBinder>().Object, true /* suppressPrefix */);
  212. // Act
  213. IExtensibleModelBinder binder = providers.GetBinder(controllerContext, bindingContext);
  214. // Assert
  215. Assert.AreEqual(typeof(CustomBinder), binder.GetType(), "Binder should've come from attribute rather than collection.");
  216. }
  217. [TestMethod]
  218. public void GetBinder_FromAttribute_Binder_ValueNotPresent_ReturnsNull() {
  219. // Arrange
  220. ControllerContext controllerContext = new ControllerContext();
  221. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext() {
  222. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_Binder)),
  223. ModelName = "foo",
  224. ValueProvider = new SimpleValueProvider() {
  225. { "bar", "barValue" }
  226. }
  227. };
  228. ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
  229. providers.RegisterBinderForType(typeof(ModelWithProviderAttribute_Binder), new Mock<IExtensibleModelBinder>().Object, true /* suppressPrefix */);
  230. // Act
  231. IExtensibleModelBinder binder = providers.GetBinder(controllerContext, bindingContext);
  232. // Assert
  233. Assert.IsNull(binder, "Binder should've come from attribute rather than collection, even if the attribute's provider returns null.");
  234. }
  235. [TestMethod]
  236. public void GetBinder_FromAttribute_Binder_ValuePresent_ReturnsBinder() {
  237. // Arrange
  238. ControllerContext controllerContext = new ControllerContext();
  239. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext() {
  240. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_Binder)),
  241. ModelName = "foo",
  242. ValueProvider = new SimpleValueProvider() {
  243. { "foo", "fooValue" }
  244. }
  245. };
  246. ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
  247. providers.RegisterBinderForType(typeof(ModelWithProviderAttribute_Binder), new Mock<IExtensibleModelBinder>().Object, true /* suppressPrefix */);
  248. // Act
  249. IExtensibleModelBinder binder = providers.GetBinder(controllerContext, bindingContext);
  250. // Assert
  251. Assert.AreEqual(typeof(CustomBinder), binder.GetType(), "Binder should've come from attribute rather than collection.");
  252. }
  253. [TestMethod]
  254. public void GetBinder_FromAttribute_Provider_ReturnsBinder() {
  255. // Arrange
  256. ControllerContext controllerContext = new ControllerContext();
  257. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext() {
  258. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_Provider))
  259. };
  260. ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
  261. providers.RegisterBinderForType(typeof(ModelWithProviderAttribute_Provider), new Mock<IExtensibleModelBinder>().Object, true /* suppressPrefix */);
  262. // Act
  263. IExtensibleModelBinder binder = providers.GetBinder(controllerContext, bindingContext);
  264. // Assert
  265. Assert.AreEqual(typeof(CustomBinder), binder.GetType(), "Binder should've come from attribute rather than collection.");
  266. }
  267. [TestMethod]
  268. public void GetBinderReturnsFirstBinderFromProviders() {
  269. // Arrange
  270. ControllerContext controllerContext = new ControllerContext();
  271. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext() {
  272. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(object))
  273. };
  274. IExtensibleModelBinder expectedBinder = new Mock<IExtensibleModelBinder>().Object;
  275. Mock<ModelBinderProvider> mockProvider = new Mock<ModelBinderProvider>();
  276. mockProvider.Setup(p => p.GetBinder(controllerContext, bindingContext)).Returns(expectedBinder);
  277. ModelBinderProviderCollection collection = new ModelBinderProviderCollection(new ModelBinderProvider[] {
  278. new Mock<ModelBinderProvider>().Object,
  279. mockProvider.Object,
  280. new Mock<ModelBinderProvider>().Object
  281. });
  282. // Act
  283. IExtensibleModelBinder returned = collection.GetBinder(controllerContext, bindingContext);
  284. // Assert
  285. Assert.AreEqual(expectedBinder, returned);
  286. }
  287. [TestMethod]
  288. public void GetBinderReturnsNullIfNoProviderMatches() {
  289. // Arrange
  290. ControllerContext controllerContext = new ControllerContext();
  291. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext() {
  292. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(object))
  293. };
  294. ModelBinderProviderCollection collection = new ModelBinderProviderCollection(new ModelBinderProvider[] {
  295. new Mock<ModelBinderProvider>().Object,
  296. });
  297. // Act
  298. IExtensibleModelBinder returned = collection.GetBinder(controllerContext, bindingContext);
  299. // Assert
  300. Assert.IsNull(returned);
  301. }
  302. [TestMethod]
  303. public void GetBinderThrowsIfBindingContextIsNull() {
  304. // Arrange
  305. ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
  306. // Act & assert
  307. ExceptionHelper.ExpectArgumentNullException(
  308. delegate {
  309. collection.GetBinder(new ControllerContext(), null);
  310. }, "bindingContext");
  311. }
  312. [TestMethod]
  313. public void GetBinderThrowsIfControllerContextIsNull() {
  314. // Arrange
  315. ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
  316. // Act & assert
  317. ExceptionHelper.ExpectArgumentNullException(
  318. delegate {
  319. collection.GetBinder(null, new ExtensibleModelBindingContext());
  320. }, "controllerContext");
  321. }
  322. [TestMethod]
  323. public void GetBinderThrowsIfModelTypeHasBindAttribute() {
  324. // Arrange
  325. ControllerContext controllerContext = new ControllerContext();
  326. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext() {
  327. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithBindAttribute))
  328. };
  329. ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
  330. // Act & assert
  331. ExceptionHelper.ExpectInvalidOperationException(
  332. delegate {
  333. collection.GetBinder(controllerContext, bindingContext);
  334. },
  335. @"The model of type 'Microsoft.Web.Mvc.ModelBinding.Test.ModelBinderProviderCollectionTest+ModelWithBindAttribute' has a [Bind] attribute. The new model binding system cannot be used with models that have type-level [Bind] attributes. Use the [BindRequired] and [BindNever] attributes on the model type or its properties instead.");
  336. }
  337. [TestMethod]
  338. public void GetRequiredBinderThrowsIfNoProviderMatches() {
  339. // Arrange
  340. ControllerContext controllerContext = new ControllerContext();
  341. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext() {
  342. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int))
  343. };
  344. ModelBinderProviderCollection collection = new ModelBinderProviderCollection(new ModelBinderProvider[] {
  345. new Mock<ModelBinderProvider>().Object,
  346. });
  347. // Act & assert
  348. ExceptionHelper.ExpectInvalidOperationException(
  349. delegate {
  350. collection.GetRequiredBinder(controllerContext, bindingContext);
  351. },
  352. @"A binder for type System.Int32 could not be located.");
  353. }
  354. [MetadataType(typeof(ModelWithBindAttribute_Buddy))]
  355. private class ModelWithBindAttribute {
  356. [Bind]
  357. private class ModelWithBindAttribute_Buddy {
  358. }
  359. }
  360. [ModelBinderProviderOptions(FrontOfList = true)]
  361. private class ProviderAtFront : ModelBinderProvider {
  362. public override IExtensibleModelBinder GetBinder(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext) {
  363. throw new NotImplementedException();
  364. }
  365. }
  366. [ExtensibleModelBinder(typeof(object))]
  367. private class ModelWithProviderAttribute_BadAttribute { }
  368. [ExtensibleModelBinder(typeof(CustomBinder))]
  369. private class ModelWithProviderAttribute_Binder { }
  370. [ExtensibleModelBinder(typeof(CustomGenericBinder<>))]
  371. private class ModelWithProviderAttribute_Binder_Generic<T> { }
  372. [ExtensibleModelBinder(typeof(CustomBinder), SuppressPrefixCheck = true)]
  373. private class ModelWithProviderAttribute_Binder_SuppressPrefix { }
  374. [ExtensibleModelBinder(typeof(CustomProvider))]
  375. private class ModelWithProviderAttribute_Provider { }
  376. private class CustomProvider : ModelBinderProvider {
  377. public override IExtensibleModelBinder GetBinder(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext) {
  378. return new CustomBinder();
  379. }
  380. }
  381. private class CustomBinder : IExtensibleModelBinder {
  382. public bool BindModel(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext) {
  383. throw new NotImplementedException();
  384. }
  385. }
  386. private class CustomGenericBinder<T> : IExtensibleModelBinder {
  387. public bool BindModel(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext) {
  388. throw new NotImplementedException();
  389. }
  390. }
  391. }
  392. }