PageRenderTime 58ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/Test/SystemWebMvcTest/Mvc/Test/DefaultModelBinderTest.cs

https://bitbucket.org/markhneedham/aspnet-mvc
C# | 1209 lines | 818 code | 221 blank | 170 comment | 12 complexity | 0ab7a72c9b9ef61f3e671762216aee85 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. namespace System.Web.Mvc.Test {
  2. using System;
  3. using System.Collections.Generic;
  4. using System.ComponentModel;
  5. using System.Globalization;
  6. using System.Web;
  7. using System.Web.Mvc;
  8. using System.Web.Routing;
  9. using System.Web.TestUtil;
  10. using Microsoft.VisualStudio.TestTools.UnitTesting;
  11. using Moq;
  12. [TestClass]
  13. [CLSCompliant(false)]
  14. public class DefaultModelBinderTest {
  15. [TestMethod]
  16. public void BindModelCallsBindModelCorePassingNewInstanceThunkIfNoInstanceThunkProvided() {
  17. // Arrange
  18. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() { ModelType = typeof(List<string>) };
  19. List<string> expected = null;
  20. Mock<DefaultModelBinderHelper> mockHelper = new Mock<DefaultModelBinderHelper>() { CallBase = true };
  21. mockHelper
  22. .Expect(h => h.PublicBindModelCore(It.IsAny<ModelBindingContext>()))
  23. .Returns(
  24. delegate(ModelBindingContext bindingContext) {
  25. Assert.AreEqual(bcHelper.ModelName, bindingContext.ModelName);
  26. Assert.AreEqual(bcHelper.ModelState, bindingContext.ModelState);
  27. Assert.AreEqual(bcHelper.ModelType, bindingContext.ModelType);
  28. Assert.AreEqual(bcHelper.ValueProvider, bindingContext.ValueProvider);
  29. expected = (List<string>)bindingContext.Model;
  30. return new ModelBinderResult(expected);
  31. });
  32. DefaultModelBinder binder = mockHelper.Object;
  33. // Act
  34. ModelBinderResult returned = binder.BindModel(bcHelper.CreateBindingContext());
  35. // Assert
  36. Assert.IsNotNull(expected);
  37. Assert.AreEqual(expected, returned.Value);
  38. }
  39. [TestMethod]
  40. public void BindModelCallsBindModelCorePassingProvidedModelThunk() {
  41. // Arrange
  42. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() { Model = new List<string>(), ModelType = typeof(List<string>) };
  43. Mock<DefaultModelBinderHelper> mockHelper = new Mock<DefaultModelBinderHelper>() { CallBase = true };
  44. mockHelper
  45. .Expect(h => h.PublicBindModelCore(It.IsAny<ModelBindingContext>()))
  46. .Returns(
  47. delegate(ModelBindingContext bindingContext) {
  48. Assert.AreEqual(bcHelper.ModelName, bindingContext.ModelName);
  49. Assert.AreEqual(bcHelper.ModelState, bindingContext.ModelState);
  50. Assert.AreEqual(bcHelper.ModelType, bindingContext.ModelType);
  51. Assert.AreEqual(bcHelper.ValueProvider, bindingContext.ValueProvider);
  52. return new ModelBinderResult(bindingContext.Model);
  53. });
  54. DefaultModelBinder binder = mockHelper.Object;
  55. // Act
  56. ModelBinderResult returned = binder.BindModel(bcHelper.CreateBindingContext());
  57. // Assert
  58. Assert.AreEqual(bcHelper.Model, returned.Value);
  59. }
  60. [TestMethod]
  61. public void BindModelCanBindComplexArrays() {
  62. // Arrange
  63. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() { ValueProvider = GetValueProviderForArray(), ModelType = typeof(MyModel[]) };
  64. DefaultModelBinder binder = new DefaultModelBinder();
  65. // Act
  66. MyModel[] returned = (MyModel[])binder.BindModel(bcHelper.CreateBindingContext()).Value;
  67. // Assert
  68. Assert.AreEqual(3, returned.Length);
  69. Assert.AreEqual(100, returned[0].ReadWriteProperty);
  70. Assert.AreEqual(101, returned[0].ReadWriteProperty2);
  71. Assert.AreEqual(200, returned[1].ReadWriteProperty);
  72. Assert.AreEqual(201, returned[1].ReadWriteProperty2);
  73. Assert.AreEqual(300, returned[2].ReadWriteProperty);
  74. Assert.AreEqual(301, returned[2].ReadWriteProperty2);
  75. }
  76. [TestMethod]
  77. public void BindModelCanBindComplexLists() {
  78. // Arrange
  79. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() { ValueProvider = GetValueProviderForArray(), ModelType = typeof(IList<MyModel>) };
  80. DefaultModelBinder binder = new DefaultModelBinder();
  81. // Act
  82. IList<MyModel> returned = (IList<MyModel>)binder.BindModel(bcHelper.CreateBindingContext()).Value;
  83. // Assert
  84. Assert.AreEqual(3, returned.Count);
  85. Assert.AreEqual(100, returned[0].ReadWriteProperty);
  86. Assert.AreEqual(101, returned[0].ReadWriteProperty2);
  87. Assert.AreEqual(200, returned[1].ReadWriteProperty);
  88. Assert.AreEqual(201, returned[1].ReadWriteProperty2);
  89. Assert.AreEqual(300, returned[2].ReadWriteProperty);
  90. Assert.AreEqual(301, returned[2].ReadWriteProperty2);
  91. }
  92. [TestMethod]
  93. public void BindModelCanBindSimpleArrays() {
  94. // Arrange
  95. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  96. mockValueProvider.Expect(p => p.GetValue("modelName")).Returns(new ValueProviderResult(new int[] { 0, 1, 2 }, "0,1,2", null));
  97. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() { ValueProvider = mockValueProvider.Object, ModelType = typeof(string[]) };
  98. DefaultModelBinder binder = new DefaultModelBinder();
  99. // Act
  100. string[] returned = (string[])binder.BindModel(bcHelper.CreateBindingContext()).Value;
  101. // Assert
  102. Assert.AreEqual(3, returned.Length);
  103. Assert.AreEqual("0", returned[0]);
  104. Assert.AreEqual("1", returned[1]);
  105. Assert.AreEqual("2", returned[2]);
  106. }
  107. [TestMethod]
  108. public void BindModelCanBindSimpleArraysUsingIndexWireFormat() {
  109. // Arrange
  110. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  111. mockValueProvider.Expect(p => p.GetValue("modelName.index")).Returns(new ValueProviderResult(new string[] { "foo", "bar", "baz" }, null, null));
  112. mockValueProvider.Expect(p => p.GetValue("modelName[foo]")).Returns(new ValueProviderResult(0, null, null));
  113. mockValueProvider.Expect(p => p.GetValue("modelName[bar]")).Returns(new ValueProviderResult(1, null, null));
  114. mockValueProvider.Expect(p => p.GetValue("modelName[baz]")).Returns(new ValueProviderResult(2, null, null));
  115. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() { ValueProvider = mockValueProvider.Object, ModelType = typeof(string[]) };
  116. DefaultModelBinder binder = new DefaultModelBinder();
  117. // Act
  118. string[] returned = (string[])binder.BindModel(bcHelper.CreateBindingContext()).Value;
  119. // Assert
  120. Assert.AreEqual(3, returned.Length);
  121. Assert.AreEqual("0", returned[0]);
  122. Assert.AreEqual("1", returned[1]);
  123. Assert.AreEqual("2", returned[2]);
  124. }
  125. [TestMethod]
  126. public void BindModelCanBindSimpleLists() {
  127. // Arrange
  128. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  129. mockValueProvider.Expect(p => p.GetValue("modelName")).Returns(new ValueProviderResult(new int[] { 0, 1, 2 }, "0,1,2", null));
  130. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() { ValueProvider = mockValueProvider.Object, ModelType = typeof(IList<string>) };
  131. DefaultModelBinder binder = new DefaultModelBinder();
  132. // Act
  133. IList<string> returned = (IList<string>)binder.BindModel(bcHelper.CreateBindingContext()).Value;
  134. // Assert
  135. Assert.AreEqual(3, returned.Count);
  136. Assert.AreEqual("0", returned[0]);
  137. Assert.AreEqual("1", returned[1]);
  138. Assert.AreEqual("2", returned[2]);
  139. }
  140. [TestMethod]
  141. public void BindModelCanBindSimpleListsUsingIndexWireFormat() {
  142. // Arrange
  143. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  144. mockValueProvider.Expect(p => p.GetValue("modelName.index")).Returns(new ValueProviderResult(new string[] { "foo", "bar", "baz" }, null, null));
  145. mockValueProvider.Expect(p => p.GetValue("modelName[foo]")).Returns(new ValueProviderResult(0, null, null));
  146. mockValueProvider.Expect(p => p.GetValue("modelName[bar]")).Returns(new ValueProviderResult(1, null, null));
  147. mockValueProvider.Expect(p => p.GetValue("modelName[baz]")).Returns(new ValueProviderResult(2, null, null));
  148. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() { ValueProvider = mockValueProvider.Object, ModelType = typeof(IList<string>) };
  149. DefaultModelBinder binder = new DefaultModelBinder();
  150. // Act
  151. IList<string> returned = (IList<string>)binder.BindModel(bcHelper.CreateBindingContext()).Value;
  152. // Assert
  153. Assert.AreEqual(3, returned.Count);
  154. Assert.AreEqual("0", returned[0]);
  155. Assert.AreEqual("1", returned[1]);
  156. Assert.AreEqual("2", returned[2]);
  157. }
  158. [TestMethod]
  159. public void BindModelCollectionReturnsNullIfUsingIndexWireFormatAndNoIndicesFound() {
  160. // Arrange
  161. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() { ModelType = typeof(ICollection<string>) };
  162. DefaultModelBinder binder = new DefaultModelBinder();
  163. // Act
  164. object returned = binder.BindModel(bcHelper.CreateBindingContext());
  165. // Assert
  166. Assert.IsNull(returned);
  167. }
  168. [TestMethod]
  169. public void BindModelCoreAddsModelErrorIfRequiredValueIsMissing() {
  170. // Arrange
  171. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  172. mockValueProvider.Expect(vp => vp.GetValue("modelName.Integer")).Returns(new ValueProviderResult("", "", null));
  173. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() { ValueProvider = mockValueProvider.Object, ModelType = typeof(IntegerContainer) };
  174. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  175. // Act
  176. object returned = helper.PublicBindModelCore(bcHelper.CreateBindingContext()).Value;
  177. // Assert
  178. Assert.IsNull(returned, "Wrapped return value should be null if model couldn't be hydrated.");
  179. ModelState modelState = bcHelper.ModelState["modelName.Integer"];
  180. Assert.AreEqual(1, modelState.Errors.Count);
  181. Assert.AreEqual("A value is required.", modelState.Errors[0].ErrorMessage);
  182. }
  183. [TestMethod]
  184. public void BindModelCoreContinuesWithSiblingPropertiesIfSomePropertySetterFails() {
  185. // Arrange
  186. MyModelWithBadPropertySetter model = new MyModelWithBadPropertySetter();
  187. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  188. mockValueProvider.Expect(vp => vp.GetValue("modelName.NormalProperty")).Returns(new ValueProviderResult("10", "10", null));
  189. mockValueProvider.Expect(vp => vp.GetValue("modelName.PropertySetterThrows")).Returns(new ValueProviderResult("20", "20", null));
  190. mockValueProvider.Expect(vp => vp.GetValue("modelName.PropertySetterThrows2")).Returns(new ValueProviderResult("30", "30", null));
  191. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() {
  192. ValueProvider = mockValueProvider.Object,
  193. Model = model,
  194. ModelType = typeof(MyModelWithBadPropertySetter),
  195. };
  196. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  197. // Act
  198. MyModelWithBadPropertySetter returned = (MyModelWithBadPropertySetter)helper.PublicBindModelCore(bcHelper.CreateBindingContext()).Value;
  199. // Assert
  200. Assert.AreEqual(model, returned, "BindModelCore() returned wrong model.");
  201. Assert.AreEqual(10, model.NormalProperty);
  202. Assert.AreEqual("The value '20' is invalid.", bcHelper.ModelState["modelName.PropertySetterThrows"].Errors[0].ErrorMessage);
  203. Assert.AreEqual("The value '30' is invalid.", bcHelper.ModelState["modelName.PropertySetterThrows2"].Errors[0].ErrorMessage);
  204. }
  205. [TestMethod]
  206. public void BindModelCoreCanUpdateComplexTypes() {
  207. // Arrange
  208. Mock<IModelBinder> mockPropertyBinder = new Mock<IModelBinder>();
  209. mockPropertyBinder
  210. .Expect(b => b.BindModel(It.IsAny<ModelBindingContext>()))
  211. .Returns(
  212. delegate(ModelBindingContext bindingContext) {
  213. switch (bindingContext.ModelName) {
  214. case "modelName.ReadWriteProperty":
  215. return new ModelBinderResult(10);
  216. case "modelName.ReadWriteProperty2":
  217. return null;
  218. default:
  219. Assert.Fail("We called into a model binder for a property we had no hope of updating, such as a read-only value type.");
  220. throw new Exception();
  221. }
  222. });
  223. Mock<DefaultModelBinderHelper> mockHelper = new Mock<DefaultModelBinderHelper>() { CallBase = true };
  224. mockHelper.Expect(h => h.PublicGetBinder(typeof(int))).Returns(mockPropertyBinder.Object);
  225. DefaultModelBinderHelper helper = mockHelper.Object;
  226. MyModel oldModel = new MyModel() { ReadWriteProperty2 = 3 };
  227. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() { ModelType = typeof(MyModel), Model = oldModel };
  228. // Act
  229. object newModel = helper.PublicBindModelCore(bcHelper.CreateBindingContext()).Value;
  230. // Assert
  231. Assert.AreSame(oldModel, newModel, "BindModelCore() should return the same object it was given.");
  232. Assert.AreEqual(4, oldModel.ReadOnlyProperty, "Can't update a read-only property.");
  233. Assert.AreEqual(10, oldModel.ReadWriteProperty, "Should be able to update a read+write property.");
  234. Assert.AreEqual(3, oldModel.ReadWriteProperty2, "Shouldn't have called setter if model binder returned null.");
  235. mockPropertyBinder.Verify();
  236. }
  237. [TestMethod]
  238. public void BindModelCoreCanUpdateComplexTypesWithReadOnlyReferenceTypeProperties() {
  239. // Arrange
  240. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() {
  241. ValueProvider = GetReflectingValueProvider(),
  242. Model = new Customer(),
  243. ModelType = typeof(Customer),
  244. ModelName = "customer"
  245. };
  246. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  247. // Act
  248. Customer customer = (Customer)helper.PublicBindModelCore(bcHelper.CreateBindingContext()).Value;
  249. // Assert
  250. Assert.IsNotNull(customer);
  251. Assert.AreEqual("customer.Address.StreetValue", customer.Address.Street);
  252. Assert.AreEqual("customer.Address.ZipValue", customer.Address.Zip);
  253. }
  254. [TestMethod]
  255. public void BindModelCoreCanUpdateGenericCollections() {
  256. // Arrange
  257. List<string> model = new List<string>();
  258. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() {
  259. ValueProvider = GetValueProviderForCollection(),
  260. Model = model,
  261. ModelType = typeof(List<string>)
  262. };
  263. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  264. // Act
  265. object returned = helper.PublicBindModelCore(bcHelper.CreateBindingContext()).Value;
  266. // Assert
  267. Assert.AreSame(model, returned);
  268. Assert.AreEqual(3, model.Count, "List does not contain the correct number of entries.");
  269. Assert.AreEqual("fooValue", model[0]);
  270. Assert.AreEqual("barValue", model[1]);
  271. Assert.AreEqual("bazValue", model[2]);
  272. }
  273. [TestMethod]
  274. public void BindModelCoreCanUpdateGenericDictionaries() {
  275. // Arrange
  276. Dictionary<string, string> model = new Dictionary<string, string>();
  277. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() {
  278. ValueProvider = GetValueProviderForDictionary(),
  279. Model = model,
  280. ModelType = typeof(Dictionary<string, string>)
  281. };
  282. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  283. // Act
  284. object returned = helper.PublicBindModelCore(bcHelper.CreateBindingContext()).Value;
  285. // Assert
  286. Assert.AreSame(model, returned);
  287. Assert.AreEqual(3, model.Count, "Dictionary does not contain the correct number of entries.");
  288. Assert.AreEqual("fooValue", model["fooKey"]);
  289. Assert.AreEqual("barValue", model["barKey"]);
  290. Assert.AreEqual("bazValue", model["bazKey"]);
  291. }
  292. [TestMethod]
  293. public void BindModelCorePreservesExistingModelErrorIfRequiredValueConversionFailed() {
  294. // Arrange
  295. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  296. mockValueProvider.Expect(vp => vp.GetValue("modelName.Integer")).Returns(new ValueProviderResult("dog", "dog", null));
  297. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() { ValueProvider = mockValueProvider.Object, ModelType = typeof(IntegerContainer) };
  298. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  299. // Act
  300. object newModel = helper.PublicBindModelCore(bcHelper.CreateBindingContext()).Value;
  301. // Assert
  302. Assert.IsNull(newModel, "Return value should be null if model couldn't be hydrated.");
  303. ModelState modelState = bcHelper.ModelState["modelName.Integer"];
  304. Assert.AreEqual(1, modelState.Errors.Count);
  305. Assert.AreEqual("The value 'dog' is invalid.", modelState.Errors[0].ErrorMessage);
  306. }
  307. [TestMethod]
  308. public void BindModelCoreRespectsIntersectionOfAllowedPropertyFilters() {
  309. // Arrange
  310. MyOtherModel model = new MyOtherModel();
  311. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() {
  312. ValueProvider = GetReflectingValueProvider(),
  313. Model = model,
  314. ModelType = typeof(MyOtherModel),
  315. PropertyFilter = new BindAttribute { Include = "Alpha, Bravo, Echo, Foxtrot" }.IsPropertyAllowed
  316. };
  317. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  318. // Act
  319. helper.PublicBindModelCore(bcHelper.CreateBindingContext());
  320. // Assert
  321. Assert.IsNull(model.Alpha, "Alpha is explicitly on the exclude list on the Type.");
  322. Assert.AreEqual("modelName.BravoValue", model.Bravo, "Bravo is explicitly on the include list in the Property Filter.");
  323. Assert.IsNull(model.Charlie, "Charlie is not on the include list in the Property Filter.");
  324. Assert.IsNull(model.Delta, "Delta is not on the include list in the Property Filter.");
  325. Assert.IsNull(model.Echo, "Echo is explicitly on the exclude list on the Type.");
  326. Assert.AreEqual("modelName.FoxtrotValue", model.Foxtrot, "Foxtrot is explicitly on the include list in the Property Filter.");
  327. }
  328. [TestMethod]
  329. public void BindModelCanBindSimpleTypes() {
  330. // Arrange
  331. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  332. mockValueProvider.Expect(p => p.GetValue("modelName")).Returns(new ValueProviderResult("42", "attemptedValue", null));
  333. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() { ValueProvider = mockValueProvider.Object, ModelType = typeof(int) };
  334. DefaultModelBinder binder = new DefaultModelBinder();
  335. // Act
  336. object returned = binder.BindModel(bcHelper.CreateBindingContext()).Value;
  337. // Assert
  338. Assert.AreEqual(42, returned);
  339. }
  340. [TestMethod]
  341. public void BindModelCoreReturnsNullIfNoPropertiesOnComplexTypeCanBeUpdated() {
  342. // Arrange
  343. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() {
  344. Model = new Customer(),
  345. ModelThunk = () => {
  346. Assert.Fail("The thunk should never be called if we never have to read the model.");
  347. throw new Exception();
  348. },
  349. ModelType = typeof(Customer),
  350. ModelName = "customer"
  351. };
  352. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  353. // Act
  354. object returned = helper.PublicBindModelCore(bcHelper.CreateBindingContext());
  355. // Assert
  356. Assert.IsNull(returned, "BindModelCore() should return null if no properties can be updated.");
  357. }
  358. [TestMethod]
  359. public void BindModelCoreSetsNullablePropertiesToNullIfUserSpecifiedEmptyStringForValue() {
  360. // Arrange
  361. IntegerContainer model = new IntegerContainer() { Integer = 42, NullableInteger = 84 };
  362. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  363. mockValueProvider.Expect(vp => vp.GetValue("modelName.NullableInteger")).Returns(new ValueProviderResult("", "", null));
  364. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() {
  365. ValueProvider = mockValueProvider.Object,
  366. Model = model,
  367. ModelType = typeof(IntegerContainer),
  368. };
  369. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  370. // Act
  371. IntegerContainer returned = (IntegerContainer)helper.PublicBindModelCore(bcHelper.CreateBindingContext()).Value;
  372. // Assert
  373. Assert.AreEqual(model, returned, "BindModelCore() returned wrong model.");
  374. Assert.AreEqual(42, model.Integer);
  375. Assert.IsNull(model.NullableInteger, "BindModelCore() should set a nullable property to null if the user specified empty string.");
  376. }
  377. [TestMethod]
  378. public void BindModelDictionaryReturnsNullIfUsingIndexWireFormatAndNoIndicesFound() {
  379. // Arrange
  380. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() { ModelType = typeof(Dictionary<int, string>) };
  381. DefaultModelBinder binder = new DefaultModelBinder();
  382. // Act
  383. object returned = binder.BindModel(bcHelper.CreateBindingContext());
  384. // Assert
  385. Assert.IsNull(returned);
  386. }
  387. [TestMethod]
  388. public void BindModelReturnsEmptyArrayIfUsingIndexWireFormatAndNoIndicesFound() {
  389. // Arrange
  390. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() { ModelType = typeof(string[]) };
  391. DefaultModelBinder binder = new DefaultModelBinder();
  392. // Act
  393. string[] returned = (string[])binder.BindModel(bcHelper.CreateBindingContext()).Value;
  394. // Assert
  395. Assert.IsNotNull(returned);
  396. Assert.AreEqual(0, returned.Length);
  397. }
  398. [TestMethod]
  399. public void BindModelReturnsRawValueIfAlreadyInstanceOfDestinationType() {
  400. // Arrange
  401. MyClassWithoutConverter expectedModel = new MyClassWithoutConverter();
  402. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  403. mockValueProvider.Expect(p => p.GetValue("modelName")).Returns(new ValueProviderResult(expectedModel, "some attempted value", null));
  404. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() { ValueProvider = mockValueProvider.Object, ModelType = typeof(MyClassWithoutConverter) };
  405. DefaultModelBinder binder = new DefaultModelBinder();
  406. // Act
  407. object returnedModel = binder.BindModel(bcHelper.CreateBindingContext()).Value;
  408. // Assert
  409. Assert.AreSame(expectedModel, returnedModel, "Binder should have short-circuited evaluation if value provider returned instance of type.");
  410. // even in the event of success, we want to populate the attempted value
  411. Assert.AreEqual(1, bcHelper.ModelState.Count);
  412. ModelState modelState = bcHelper.ModelState["modelName"];
  413. Assert.AreEqual("some attempted value", modelState.AttemptedValue);
  414. Assert.AreEqual(0, modelState.Errors.Count);
  415. }
  416. [TestMethod]
  417. public void BindModelThrowsIfBindingContextIsNull() {
  418. // Arrange
  419. DefaultModelBinder binder = new DefaultModelBinder();
  420. // Act & assert
  421. ExceptionHelper.ExpectArgumentNullException(
  422. delegate {
  423. binder.BindModel(null);
  424. }, "bindingContext");
  425. }
  426. [TestMethod]
  427. public void BindProperty() {
  428. // Arrange
  429. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper();
  430. Mock<IModelBinder> mockPropertyBinder = new Mock<IModelBinder>();
  431. mockPropertyBinder
  432. .Expect(b => b.BindModel(It.IsAny<ModelBindingContext>()))
  433. .Returns(
  434. delegate(ModelBindingContext bindingContext) {
  435. return new ModelBinderResult(bindingContext.ModelName + "_Value");
  436. });
  437. Mock<DefaultModelBinderHelper> mockHelper = new Mock<DefaultModelBinderHelper>() { CallBase = true };
  438. mockHelper.Expect(h => h.PublicGetBinder(typeof(string))).Returns(mockPropertyBinder.Object);
  439. DefaultModelBinderHelper helper = mockHelper.Object;
  440. // Act
  441. object returned = helper.PublicBindProperty(bcHelper.CreateBindingContext(), typeof(string), () => null, "propertyName").Value;
  442. // Assert
  443. Assert.AreEqual("modelName.propertyName_Value", returned);
  444. }
  445. [TestMethod]
  446. public void ConvertSimpleArrayTypeCanConvertArraysToArrays() {
  447. // Arrange
  448. int[] original = new int[] { 1, 20, 42 };
  449. // Act
  450. string[] converted = (string[])DefaultModelBinderHelper.PublicConvertSimpleArrayType(CultureInfo.InvariantCulture, original, typeof(string[]));
  451. // Assert
  452. Assert.IsNotNull(converted);
  453. Assert.AreEqual(3, converted.Length);
  454. Assert.AreEqual("1", converted[0]);
  455. Assert.AreEqual("20", converted[1]);
  456. Assert.AreEqual("42", converted[2]);
  457. }
  458. [TestMethod]
  459. public void ConvertSimpleArrayTypeCanConvertArraysToSingleElements() {
  460. // Arrange
  461. int[] original = new int[] { 1, 20, 42 };
  462. // Act
  463. string converted = (string)DefaultModelBinderHelper.PublicConvertSimpleArrayType(CultureInfo.InvariantCulture, original, typeof(string));
  464. // Assert
  465. Assert.AreEqual("1", converted);
  466. }
  467. [TestMethod]
  468. public void ConvertSimpleArrayTypeCanConvertSingleElementsToArrays() {
  469. // Arrange
  470. int original = 42;
  471. // Act
  472. string[] converted = (string[])DefaultModelBinderHelper.PublicConvertSimpleArrayType(CultureInfo.InvariantCulture, original, typeof(string[]));
  473. // Assert
  474. Assert.IsNotNull(converted);
  475. Assert.AreEqual(1, converted.Length);
  476. Assert.AreEqual("42", converted[0]);
  477. }
  478. [TestMethod]
  479. public void ConvertSimpleArrayTypeCanConvertSingleElementsToSingleElements() {
  480. // Arrange
  481. int original = 42;
  482. // Act
  483. string converted = (string)DefaultModelBinderHelper.PublicConvertSimpleArrayType(CultureInfo.InvariantCulture, original, typeof(string));
  484. // Assert
  485. Assert.IsNotNull(converted);
  486. Assert.AreEqual("42", converted);
  487. }
  488. [TestMethod]
  489. public void ConvertSimpleArrayTypeReturnsNullIfTryingToConvertEmptyArrayToSingleElement() {
  490. // Act
  491. object outValue = DefaultModelBinderHelper.PublicConvertSimpleArrayType(CultureInfo.InvariantCulture, new int[0], typeof(int));
  492. // Assert
  493. Assert.IsNull(outValue);
  494. }
  495. [TestMethod]
  496. public void ConvertSimpleArrayTypeReturnsNullIfValueIsNull() {
  497. // Act
  498. object outValue = DefaultModelBinderHelper.PublicConvertSimpleArrayType(CultureInfo.InvariantCulture, null /* value */, typeof(int[]));
  499. // Assert
  500. Assert.IsNull(outValue);
  501. }
  502. [TestMethod]
  503. public void ConvertSimpleArrayTypeReturnsValueIfInstanceOfDestinationType() {
  504. // Arrange
  505. string[] original = new string[] { "some string" };
  506. // Act
  507. object outValue = DefaultModelBinderHelper.PublicConvertSimpleArrayType(CultureInfo.InvariantCulture, original, typeof(string[]));
  508. // Assert
  509. Assert.AreSame(original, outValue);
  510. }
  511. [TestMethod]
  512. public void ConvertSimpleTypeChecksCanConvertFrom() {
  513. // Arrange
  514. object original = "someValue";
  515. // Act
  516. StringContainer returned = (StringContainer)DefaultModelBinderHelper.PublicConvertSimpleType(CultureInfo.GetCultureInfo("fr-FR"), original, typeof(StringContainer));
  517. // Assert
  518. Assert.AreEqual(returned.Value, "someValue (fr-FR)");
  519. }
  520. [TestMethod]
  521. public void ConvertSimpleTypeChecksCanConvertTo() {
  522. // Arrange
  523. object original = new StringContainer("someValue");
  524. // Act
  525. string returned = (string)DefaultModelBinderHelper.PublicConvertSimpleType(CultureInfo.GetCultureInfo("en-US"), original, typeof(string));
  526. // Assert
  527. Assert.AreEqual(returned, "someValue (en-US)");
  528. }
  529. [TestMethod]
  530. public void ConvertSimpleTypeReturnsNullIfValueIsEmptyString() {
  531. // Act
  532. object outValue = DefaultModelBinderHelper.PublicConvertSimpleType(CultureInfo.InvariantCulture, "", typeof(int));
  533. // Assert
  534. Assert.IsNull(outValue);
  535. }
  536. [TestMethod]
  537. public void ConvertSimpleTypeReturnsNullIfValueIsNull() {
  538. // Act
  539. object outValue = DefaultModelBinderHelper.PublicConvertSimpleType(CultureInfo.InvariantCulture, null /* value */, typeof(int));
  540. // Assert
  541. Assert.IsNull(outValue);
  542. }
  543. [TestMethod]
  544. public void ConvertSimpleTypeReturnsValueIfInstanceOfDestinationType() {
  545. // Act
  546. object outValue = DefaultModelBinderHelper.PublicConvertSimpleType(CultureInfo.InvariantCulture, "some string", typeof(object));
  547. // Assert
  548. Assert.AreEqual("some string", outValue);
  549. }
  550. [TestMethod]
  551. public void ConvertSimpleTypeThrowsIfConverterThrows() {
  552. // Arrange
  553. Type destinationType = typeof(StringContainer);
  554. // Act & Assert
  555. // Will throw since the custom converter assumes the first 5 characters to be digits
  556. InvalidOperationException exception = ExceptionHelper.ExpectInvalidOperationException(
  557. delegate {
  558. DefaultModelBinderHelper.PublicConvertSimpleType(CultureInfo.InvariantCulture, "x", destinationType);
  559. },
  560. "The parameter conversion from type 'System.String' to type 'System.Web.Mvc.Test.DefaultModelBinderTest+StringContainer' failed. See the inner exception for more information.");
  561. Exception innerException = exception.InnerException;
  562. Assert.AreEqual("Value must have at least 3 characters.", innerException.Message);
  563. }
  564. [TestMethod]
  565. public void ConvertSimpleTypeThrowsIfNoConverterExists() {
  566. // Arrange
  567. Type destinationType = typeof(MyClassWithoutConverter);
  568. // Act & Assert
  569. ExceptionHelper.ExpectInvalidOperationException(
  570. delegate {
  571. DefaultModelBinderHelper.PublicConvertSimpleType(CultureInfo.InvariantCulture, "x", destinationType);
  572. },
  573. "The parameter conversion from type 'System.String' to type 'System.Web.Mvc.Test.DefaultModelBinderTest+MyClassWithoutConverter' failed because no TypeConverter can convert between these types.");
  574. }
  575. [TestMethod]
  576. public void CreateInstanceCreatesModelInstance() {
  577. // Arrange
  578. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  579. // Act
  580. object modelObj = helper.PublicCreateModel(null, typeof(Guid));
  581. // Assert
  582. Assert.AreEqual(Guid.Empty, modelObj);
  583. }
  584. [TestMethod]
  585. public void CreateInstanceCreatesModelInstanceForGenericICollection() {
  586. // Arrange
  587. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  588. // Act
  589. object modelObj = helper.PublicCreateModel(null, typeof(ICollection<Guid>));
  590. // Assert
  591. Assert.IsInstanceOfType(modelObj, typeof(ICollection<Guid>));
  592. }
  593. [TestMethod]
  594. public void CreateInstanceCreatesModelInstanceForGenericIDictionary() {
  595. // Arrange
  596. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  597. // Act
  598. object modelObj = helper.PublicCreateModel(null, typeof(IDictionary<string, Guid>));
  599. // Assert
  600. Assert.IsInstanceOfType(modelObj, typeof(IDictionary<string, Guid>));
  601. }
  602. [TestMethod]
  603. public void CreateInstanceCreatesModelInstanceForGenericIList() {
  604. // Arrange
  605. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  606. // Act
  607. object modelObj = helper.PublicCreateModel(null, typeof(IList<Guid>));
  608. // Assert
  609. Assert.IsInstanceOfType(modelObj, typeof(IList<Guid>));
  610. }
  611. [TestMethod]
  612. public void CreateSubIndexNameReturnsPrefixPlusIndex() {
  613. // Arrange
  614. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  615. // Act
  616. string newName = helper.PublicCreateSubIndexName("somePrefix", "someIndex");
  617. // Assert
  618. Assert.AreEqual("somePrefix[someIndex]", newName);
  619. }
  620. [TestMethod]
  621. public void CreateSubIndexNameReturnsIndexNameIfPrefixIsEmpty() {
  622. // Arrange
  623. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  624. // Act
  625. string newName = helper.PublicCreateSubIndexName(String.Empty, "someIndex");
  626. // Assert
  627. Assert.AreEqual("[someIndex]", newName);
  628. }
  629. [TestMethod]
  630. public void CreateSubIndexNameReturnsIndexNameIfPrefixIsNull() {
  631. // Arrange
  632. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  633. // Act
  634. string newName = helper.PublicCreateSubIndexName(null, "someIndex");
  635. // Assert
  636. Assert.AreEqual("[someIndex]", newName);
  637. }
  638. [TestMethod]
  639. public void CreateSubPropertyNameReturnsPrefixPlusPropertyName() {
  640. // Arrange
  641. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  642. // Act
  643. string newName = helper.PublicCreateSubPropertyName("somePrefix", "someProperty");
  644. // Assert
  645. Assert.AreEqual("somePrefix.someProperty", newName);
  646. }
  647. [TestMethod]
  648. public void CreateSubPropertyNameReturnsPropertyNameIfPrefixIsEmpty() {
  649. // Arrange
  650. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  651. // Act
  652. string newName = helper.PublicCreateSubPropertyName(String.Empty, "someProperty");
  653. // Assert
  654. Assert.AreEqual("someProperty", newName);
  655. }
  656. [TestMethod]
  657. public void CreateSubPropertyNameReturnsPropertyNameIfPrefixIsNull() {
  658. // Arrange
  659. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  660. // Act
  661. string newName = helper.PublicCreateSubPropertyName(null, "someProperty");
  662. // Assert
  663. Assert.AreEqual("someProperty", newName);
  664. }
  665. [TestMethod]
  666. public void GetBinderReturnsBinderRegisteredForType() {
  667. // Arrange
  668. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  669. // Act
  670. IModelBinder binder = helper.PublicGetBinder(typeof(MyStringModel));
  671. // Assert
  672. Assert.IsInstanceOfType(binder, typeof(MyStringModelBinder));
  673. }
  674. [TestMethod]
  675. public void GetSimpleTypePopulatesModelStateOnFailure() {
  676. // Arrange
  677. CultureInfo cultureInfo = CultureInfo.GetCultureInfo("en-GB");
  678. ValueProviderResult result = new ValueProviderResult("rawValue", "attemptedValue", cultureInfo);
  679. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  680. mockValueProvider.Expect(p => p.GetValue("modelName")).Returns(result);
  681. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  682. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() {
  683. ValueProvider = mockValueProvider.Object,
  684. ModelType = typeof(int)
  685. };
  686. // Act
  687. object model = helper.PublicGetSimpleType(bcHelper.CreateBindingContext()).Value;
  688. // Assert
  689. Assert.IsNull(model, "GetSimpleType() should return null on failure.");
  690. ModelStateDictionary modelStateDict = bcHelper.ModelState;
  691. Assert.AreEqual(1, modelStateDict.Count);
  692. ModelState modelState = modelStateDict["modelName"];
  693. Assert.AreEqual("attemptedValue", modelState.AttemptedValue);
  694. Assert.AreEqual(1, modelState.Errors.Count);
  695. ModelError modelError = modelState.Errors[0];
  696. Assert.IsNull(modelError.Exception, "Should not propagate exception to model error dictionary - possible information disclosure.");
  697. Assert.AreEqual("The value 'attemptedValue' is invalid.", modelError.ErrorMessage);
  698. }
  699. [TestMethod]
  700. public void GetSimpleTypeReturnsConvertedValueOnSuccess() {
  701. // Arrange
  702. CultureInfo cultureInfo = CultureInfo.GetCultureInfo("en-GB");
  703. ValueProviderResult result = new ValueProviderResult("input value", "attemptedValue", cultureInfo);
  704. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  705. mockValueProvider.Expect(p => p.GetValue("modelName")).Returns(result);
  706. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  707. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() {
  708. ValueProvider = mockValueProvider.Object,
  709. ModelType = typeof(string)
  710. };
  711. // Act
  712. object model = helper.PublicGetSimpleType(bcHelper.CreateBindingContext()).Value;
  713. // Assert
  714. Assert.AreEqual("input value", model);
  715. }
  716. [TestMethod]
  717. public void GetSimpleTypeReturnsNullIfValueProviderReturnsNull() {
  718. // Arrange
  719. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper();
  720. DefaultModelBinderHelper binder = new DefaultModelBinderHelper();
  721. // Act
  722. object model = binder.PublicGetSimpleType(bcHelper.CreateBindingContext());
  723. // Assert
  724. Assert.IsNull(model, "GetSimpleType() should return null if the value provider returns null.");
  725. }
  726. [TestMethod]
  727. public void GetSimpleTypeSetsModelStateAttemptedValue() {
  728. // Arrange
  729. CultureInfo cultureInfo = CultureInfo.GetCultureInfo("en-GB");
  730. ValueProviderResult result = new ValueProviderResult("42", "some attempted value", cultureInfo);
  731. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  732. mockValueProvider.Expect(p => p.GetValue("modelName")).Returns(result);
  733. DefaultModelBinderHelper helper = new DefaultModelBinderHelper();
  734. ModelBindingContextHelper bcHelper = new ModelBindingContextHelper() {
  735. ValueProvider = mockValueProvider.Object,
  736. ModelType = typeof(int)
  737. };
  738. // Act
  739. object model = helper.PublicGetSimpleType(bcHelper.CreateBindingContext()).Value;
  740. // Assert
  741. Assert.AreEqual(42, model);
  742. ModelStateDictionary modelStateDict = bcHelper.ModelState;
  743. Assert.AreEqual(1, modelStateDict.Count);
  744. ModelState modelState = modelStateDict["modelName"];
  745. Assert.AreEqual("some attempted value", modelState.AttemptedValue);
  746. Assert.AreEqual(0, modelState.Errors.Count);
  747. }
  748. [TestMethod]
  749. public void IsSimpleTypeReturnsFalseForArraysOfReferenceTypes() {
  750. // Act
  751. bool IsSimpleType = DefaultModelBinderHelper.PublicIsSimpleType(typeof(object[]));
  752. // Assert
  753. Assert.IsFalse(IsSimpleType);
  754. }
  755. [TestMethod]
  756. public void IsSimpleTypeReturnsFalseForReferenceTypes() {
  757. // Act
  758. bool IsSimpleType = DefaultModelBinderHelper.PublicIsSimpleType(typeof(object));
  759. // Assert
  760. Assert.IsFalse(IsSimpleType);
  761. }
  762. [TestMethod]
  763. public void IsSimpleTypeReturnsTrueForArraysOfValueTypes() {
  764. // Act
  765. bool IsSimpleType = DefaultModelBinderHelper.PublicIsSimpleType(typeof(int[]));
  766. // Assert
  767. Assert.IsTrue(IsSimpleType);
  768. }
  769. [TestMethod]
  770. public void IsSimpleTypeReturnsTrueForArraysOfStrings() {
  771. // Act
  772. bool IsSimpleType = DefaultModelBinderHelper.PublicIsSimpleType(typeof(string[]));
  773. // Assert
  774. Assert.IsTrue(IsSimpleType);
  775. }
  776. [TestMethod]
  777. public void IsSimpleTypeReturnsTrueForNullableValueTypes() {
  778. // Act
  779. bool IsSimpleType = DefaultModelBinderHelper.PublicIsSimpleType(typeof(int?));
  780. // Assert
  781. Assert.IsTrue(IsSimpleType);
  782. }
  783. [TestMethod]
  784. public void IsSimpleTypeReturnsTrueForString() {
  785. // Act
  786. bool IsSimpleType = DefaultModelBinderHelper.PublicIsSimpleType(typeof(string));
  787. // Assert
  788. Assert.IsTrue(IsSimpleType);
  789. }
  790. [TestMethod]
  791. public void IsSimpleTypeReturnsTrueForValueTypes() {
  792. // Act
  793. bool IsSimpleType = DefaultModelBinderHelper.PublicIsSimpleType(typeof(int));
  794. // Assert
  795. Assert.IsTrue(IsSimpleType);
  796. }
  797. private static ControllerContext GetControllerContext() {
  798. return new ControllerContext(new Mock<HttpContextBase>().Object, new RouteData(), new Mock<ControllerBase>().Object);
  799. }
  800. private static IValueProvider GetReflectingValueProvider() {
  801. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  802. mockValueProvider
  803. .Expect(p => p.GetValue(It.IsAny<string>()))
  804. .Returns(
  805. delegate(string name) {
  806. return new ValueProviderResult(name + "Value", name + "Value", CultureInfo.InvariantCulture);
  807. });
  808. return mockValueProvider.Object;
  809. }
  810. private static IValueProvider GetValueProviderForArray() {
  811. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  812. mockValueProvider.Expect(p => p.GetValue("modelName.index")).Returns(new ValueProviderResult(new string[] { "0", "1", "2" }, "attemptedValue", null));
  813. mockValueProvider.Expect(p => p.GetValue("modelName[0].ReadWriteProperty")).Returns(new ValueProviderResult("100", "attemptedValue", null));
  814. mockValueProvider.Expect(p => p.GetValue("modelName[0].ReadWriteProperty2")).Returns(new ValueProviderResult("101", "attemptedValue", null));
  815. mockValueProvider.Expect(p => p.GetValue("modelName[1].ReadWriteProperty")).Returns(new ValueProviderResult("200", "attemptedValue", null));
  816. mockValueProvider.Expect(p => p.GetValue("modelName[1].ReadWriteProperty2")).Returns(new ValueProviderResult("201", "attemptedValue", null));
  817. mockValueProvider.Expect(p => p.GetValue("modelName[2].ReadWriteProperty")).Returns(new ValueProviderResult("300", "attemptedValue", null));
  818. mockValueProvider.Expect(p => p.GetValue("modelName[2].ReadWriteProperty2")).Returns(new ValueProviderResult("301", "attemptedValue", null));
  819. return mockValueProvider.Object;
  820. }
  821. private static IValueProvider GetValueProviderForCollection() {
  822. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  823. mockValueProvider.Expect(p => p.GetValue("modelName.index")).Returns(new ValueProviderResult(new string[] { "0", "1", "2" }, "attemptedValue", null));
  824. mockValueProvider.Expect(p => p.GetValue("modelName[0]")).Returns(new ValueProviderResult("fooValue", "attemptedValue", null));
  825. mockValueProvider.Expect(p => p.GetValue("modelName[1]")).Returns(new ValueProviderResult("barValue", "attemptedValue", null));
  826. mockValueProvider.Expect(p => p.GetValue("modelName[2]")).Returns(new ValueProviderResult("bazValue", "attemptedValue", null));
  827. return mockValueProvider.Object;
  828. }
  829. private static IValueProvider GetValueProviderForDictionary() {
  830. Mock<IValueProvider> mockValueProvider = new Mock<IValueProvider>();
  831. mockValueProvider.Expect(p => p.GetValue("modelName.index")).Returns(new ValueProviderResult(new string[] { "0", "1", "2" }, "attemptedValue", null));
  832. mockValueProvider.Expect(p => p.GetValue("modelName[0].key")).Returns(new ValueProviderResult("fooKey", "attemptedValue", null));
  833. mockValueProvider.Expect(p => p.GetValue("modelName[0].value")).Returns(new ValueProviderResult("fooValue", "attemptedValue", null));
  834. mockValueProvider.Expect(p => p.GetValue("modelName[1].key")).Returns(new ValueProviderResult("barKey", "attemptedValue", null));
  835. mockValueProvider.Expect(p => p.GetValue("modelName[1].value")).Returns(new ValueProviderResult("barValue", "attemptedValue", null));
  836. mockValueProvider.Expect(p => p.GetValue("modelName[2].key")).Returns(new ValueProviderResult("bazKey", "attemptedValue", null));
  837. mockValueProvider.Expect(p => p.GetValue("modelName[2].value")).Returns(new ValueProviderResult("bazValue", "attemptedValue", null));
  838. return mockValueProvider.Object;
  839. }
  840. [ModelBinder(typeof(DefaultModelBinder))]
  841. private class MyModel {
  842. public int ReadOnlyProperty {
  843. get { return 4; }
  844. }
  845. public int ReadWriteProperty { get; set; }
  846. public int ReadWriteProperty2 { get; set; }
  847. }
  848. private class MyModelWithBadPropertySetter {
  849. public int NormalProperty { get; set; }
  850. public int PropertySetterThrows {
  851. get {
  852. return 0;
  853. }
  854. set {
  855. throw new Exception("This property setter throws.");
  856. }
  857. }
  858. public int PropertySetterThrows2 {
  859. get {
  860. return 0;
  861. }
  862. set {
  863. throw new Exception("This property setter throws.");
  864. }
  865. }
  866. }
  867. private class MyClassWithoutConverter {
  868. }
  869. [Bind(Exclude = "Alpha,E…

Large files files are truncated, but you can click here to view the full file