Added functionaltests for ModelMetadataType attribute and moved TryValidateModel tests actions to ValidationWebSite

This commit is contained in:
Kirthi Krishnamraju 2015-01-15 16:57:51 -08:00
parent 08a578d01f
commit cbed666cba
18 changed files with 595 additions and 104 deletions

15
Mvc.sln
View File

@ -126,6 +126,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.Common
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "XmlFormattersWebSite", "test\WebSites\XmlFormattersWebSite\XmlFormattersWebSite.kproj", "{C3123A70-41C4-4122-AD1C-D35DF8958DD7}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ValidationWebSite", "test\WebSites\ValidationWebSite\ValidationWebSite.kproj", "{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -688,6 +690,18 @@ Global
{BDEEBE09-C0C4-433C-B0B8-8478C9776996}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{BDEEBE09-C0C4-433C-B0B8-8478C9776996}.Release|x86.ActiveCfg = Release|Any CPU
{BDEEBE09-C0C4-433C-B0B8-8478C9776996}.Release|x86.Build.0 = Release|Any CPU
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Debug|x86.ActiveCfg = Debug|Any CPU
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Debug|x86.Build.0 = Debug|Any CPU
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Release|Any CPU.Build.0 = Release|Any CPU
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Release|x86.ActiveCfg = Release|Any CPU
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Release|x86.Build.0 = Release|Any CPU
{0449D6D2-BE1B-4E29-8E1B-444420802C03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0449D6D2-BE1B-4E29-8E1B-444420802C03}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0449D6D2-BE1B-4E29-8E1B-444420802C03}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@ -773,5 +787,6 @@ Global
{BDEEBE09-C0C4-433C-B0B8-8478C9776996} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{0449D6D2-BE1B-4E29-8E1B-444420802C03} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{C3123A70-41C4-4122-AD1C-D35DF8958DD7} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,182 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.TestHost;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNet.Mvc.FunctionalTests
{
public class ModelMetadataAttributeTest
{
private readonly IServiceProvider _services = TestHelper.CreateServices(nameof(ValidationWebSite));
private readonly Action<IApplicationBuilder> _app = new ValidationWebSite.Startup().Configure;
[Fact]
public async Task ModelMetaDataTypeAttribute_ValidBaseClass_EmptyResponseBody()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.CreateClient();
var input = "{ \"Name\": \"MVC\", \"Contact\":\"4258959019\", \"Category\":\"Technology\"," +
"\"CompanyName\":\"Microsoft\", \"Country\":\"USA\",\"Price\": 21, \"ProductDetails\": {\"Detail1\": \"d1\"," +
" \"Detail2\": \"d2\", \"Detail3\": \"d3\"}}";
var content = new StringContent(input, Encoding.UTF8, "application/json");
var url = "http://localhost/ModelMetadataTypeValidation/ValidateProductViewModelIncludingMetadata";
// Act
var response = await client.PostAsync(url, content);
// Assert
var body = await response.Content.ReadAsStringAsync();
Assert.Equal("{}", body);
}
[Fact]
public async Task ModelMetaDataTypeAttribute_InvalidPropertiesAndSubPropertiesOnBaseClass_ReturnsErrors()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.CreateClient();
var input = "{ \"Price\": 2, \"ProductDetails\": {\"Detail1\": \"d1\"}}";
var content = new StringContent(input, Encoding.UTF8, "application/json");
var url = "http://localhost/ModelMetadataTypeValidation/ValidateProductViewModelIncludingMetadata";
// Act
var response = await client.PostAsync(url, content);
// Assert
var body = await response.Content.ReadAsStringAsync();
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(body);
Assert.Equal(6, json.Count);
Assert.Equal("CompanyName cannot be null or empty.", json["product.CompanyName"]);
Assert.Equal("The field Price must be between 20 and 100.", json["product.Price"]);
Assert.Equal("The Category field is required.", json["product.Category"]);
Assert.Equal("The Contact Us field is required.", json["product.Contact"]);
Assert.Equal("The Detail2 field is required.", json["product.ProductDetails.Detail2"]);
Assert.Equal("The Detail3 field is required.", json["product.ProductDetails.Detail3"]);
}
[Fact]
public async Task ModelMetaDataTypeAttribute_InvalidComplexTypePropertyOnBaseClass_ReturnsErrors()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.CreateClient();
var input = "{ \"Contact\":\"4255678765\", \"Category\":\"Technology\"," +
"\"CompanyName\":\"Microsoft\", \"Country\":\"USA\",\"Price\": 21 }";
var content = new StringContent(input, Encoding.UTF8, "application/json");
var url = "http://localhost/ModelMetadataTypeValidation/ValidateProductViewModelIncludingMetadata";
// Act
var response = await client.PostAsync(url, content);
// Assert
var body = await response.Content.ReadAsStringAsync();
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(body);
Assert.Equal(1, json.Count);
Assert.Equal("The ProductDetails field is required.", json["product.ProductDetails"]);
}
[Fact]
public async Task ModelMetaDataTypeAttribute_InvalidClassAttributeOnBaseClass_ReturnsErrors()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.CreateClient();
var input = "{ \"Contact\":\"4258959019\", \"Category\":\"Technology\"," +
"\"CompanyName\":\"Microsoft\", \"Country\":\"UK\",\"Price\": 21, \"ProductDetails\": {\"Detail1\": \"d1\"," +
" \"Detail2\": \"d2\", \"Detail3\": \"d3\"}}";
var content = new StringContent(input, Encoding.UTF8, "application/json");
var url = "http://localhost/ModelMetadataTypeValidation/ValidateProductViewModelIncludingMetadata";
// Act
var response = await client.PostAsync(url, content);
// Assert
var body = await response.Content.ReadAsStringAsync();
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(body);
Assert.Equal(1, json.Count);
Assert.Equal("Product must be made in the USA if it is not named.", json["product"]);
}
[Fact]
public async Task ModelMetaDataTypeAttribute_ValidDerivedClass_EmptyResponseBody()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.CreateClient();
var input = "{ \"Name\": \"MVC\", \"Contact\":\"4258959019\", \"Category\":\"Technology\"," +
"\"CompanyName\":\"Microsoft\", \"Country\":\"USA\", \"Version\":\"2\"," +
"\"DatePurchased\": \"/Date(1297246301973)/\", \"Price\" : \"110\" }";
var content = new StringContent(input, Encoding.UTF8, "application/json");
var url = "http://localhost/ModelMetadataTypeValidation/ValidateSoftwareViewModelIncludingMetadata";
// Act
var response = await client.PostAsync(url, content);
// Assert
var body = await response.Content.ReadAsStringAsync();
Assert.Equal("{}", body);
}
[Fact]
public async Task ModelMetaDataTypeAttribute_InvalidPropertiesOnDerivedClass_ReturnsErrors()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.CreateClient();
var input = "{ \"Name\": \"MVC\", \"Contact\":\"425-895-9019\", \"Category\":\"Technology\"," +
"\"CompanyName\":\"Microsoft\", \"Country\":\"USA\",\"Price\": 2}";
var content = new StringContent(input, Encoding.UTF8, "application/json");
var url = "http://localhost/ModelMetadataTypeValidation/ValidateSoftwareViewModelIncludingMetadata";
// Act
var response = await client.PostAsync(url, content);
// Assert
var body = await response.Content.ReadAsStringAsync();
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(body);
Assert.Equal(2, json.Count);
Assert.Equal("The field Price must be between 100 and 200.", json["software.Price"]);
Assert.Equal("The field Contact must be a string with a maximum length of 10.", json["software.Contact"]);
}
[Fact]
public async Task ModelMetaDataTypeAttribute_InvalidClassAttributeOnBaseClassProduct_ReturnsErrors()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.CreateClient();
var input = "{ \"Contact\":\"4258959019\", \"Category\":\"Technology\"," +
"\"CompanyName\":\"Microsoft\", \"Country\":\"UK\",\"Version\":\"2\"," +
"\"DatePurchased\": \"/Date(1297246301973)/\", \"Price\" : \"110\" }";
var content = new StringContent(input, Encoding.UTF8, "application/json");
var url = "http://localhost/ModelMetadataTypeValidation/ValidateSoftwareViewModelIncludingMetadata";
// Act
var response = await client.PostAsync(url, content);
// Assert
var body = await response.Content.ReadAsStringAsync();
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(body);
Assert.Equal(1, json.Count);
Assert.Equal("Product must be made in the USA if it is not named.", json["software"]);
}
}
}

View File

@ -4,6 +4,8 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.TestHost;
@ -14,60 +16,76 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
{
public class TryValidateModelTest
{
private readonly IServiceProvider _services = TestHelper.CreateServices(nameof(FormatterWebSite));
private readonly Action<IApplicationBuilder> _app = new FormatterWebSite.Startup().Configure;
private readonly IServiceProvider _services = TestHelper.CreateServices(nameof(ValidationWebSite));
private readonly Action<IApplicationBuilder> _app = new ValidationWebSite.Startup().Configure;
[Fact]
public async Task TryValidateModel_SimpleModelInvalidProperties()
public async Task TryValidateModel_ClearParameterValidationError_ReturnsErrorsForInvalidProperties()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.CreateClient();
var input = "{ \"Price\": 2, \"Contact\": \"acvrdzersaererererfdsfdsfdsfsdf\", "+
"\"ProductDetails\": {\"Detail1\": \"d1\", \"Detail2\": \"d2\", \"Detail3\": \"d3\"}}";
var content = new StringContent(input, Encoding.UTF8, "application/json");
var url =
"http://localhost/ModelMetadataTypeValidation/" +
"TryValidateModelAfterClearingValidationErrorInParameter?theImpossibleString=test";
// Act
var response = await client.GetAsync("http://localhost/TryValidateModel/GetInvalidUser");
var response = await client.PostAsync(url, content);
// Assert
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
var json = JsonConvert.DeserializeObject<Dictionary<string, string[]>>(
await response.Content.ReadAsStringAsync());
Assert.Equal("The field Id must be between 1 and 2000.", json["Id"][0]);
Assert.Equal(
"The field Name must be a string or array type with a minimum length of '5'.", json["Name"][0]);
var body = await response.Content.ReadAsStringAsync();
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(body);
Assert.Equal(8, json.Count);
Assert.Equal("CompanyName cannot be null or empty.", json["product.CompanyName"]);
Assert.Equal("The field Price must be between 20 and 100.", json["product.Price"]);
Assert.Equal("The Category field is required.", json["product.Category"]);
Assert.Equal("The field Contact Us must be a string with a maximum length of 20."+
"The field Contact Us must match the regular expression '^[0-9]*$'.", json["product.Contact"]);
Assert.Equal("CompanyName cannot be null or empty.", json["CompanyName"]);
Assert.Equal("The field Price must be between 20 and 100.", json["Price"]);
Assert.Equal("The Category field is required.", json["Category"]);
Assert.Equal("The field Contact Us must be a string with a maximum length of 20."+
"The field Contact Us must match the regular expression '^[0-9]*$'.", json["Contact"]);
}
[Fact]
public async Task TryValidateModel_DerivedModelInvalidType()
public async Task TryValidateModel_InvalidTypeOnDerivedModel_ReturnsErrors()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.CreateClient();
var url =
"http://localhost/ModelMetadataTypeValidation/TryValidateModelSoftwareViewModelWithPrefix";
// Act
var response = await client.GetAsync("http://localhost/TryValidateModel/GetInvalidAdminWithPrefix");
var response = await client.GetAsync(url);
// Assert
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
var json = JsonConvert.DeserializeObject<Dictionary<string, string[]>>(
await response.Content.ReadAsStringAsync());
Assert.Equal("AdminAccessCode property does not have the right value", json["admin"][0]);
var body = await response.Content.ReadAsStringAsync();
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(body);
Assert.Equal(1, json.Count);
Assert.Equal("Product must be made in the USA if it is not named.", json["software"]);
}
[Fact]
public async Task TryValidateModel_ValidDerivedModel()
public async Task TryValidateModel_ValidDerivedModel_ReturnsEmptyResponseBody()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.CreateClient();
var url =
"http://localhost/ModelMetadataTypeValidation/TryValidateModelValidModelNoPrefix";
// Act
var response = await client.GetAsync("http://localhost/TryValidateModel/GetValidAdminWithPrefix");
var response = await client.GetAsync(url);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Admin user created successfully", await response.Content.ReadAsStringAsync());
var body = await response.Content.ReadAsStringAsync();
Assert.Equal("{}", body);
}
}
}

View File

@ -32,6 +32,7 @@
"TagHelperSample.Web": "1.0.0",
"TagHelpersWebSite": "1.0.0",
"UrlHelperWebSite": "1.0.0",
"ValidationWebSite": "1.0.0",
"ValueProvidersWebSite": "1.0.0",
"VersioningWebSite": "1.0.0",
"ViewComponentWebSite": "1.0.0",

View File

@ -1,64 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Mvc;
namespace FormatterWebSite
{
public class TryValidateModelController : Controller
{
[HttpGet]
public IActionResult GetInvalidUser()
{
var user = new User
{
Id = 0,
Name = "x"
};
// If ModelState.InValid is false return BadRequestOjectResult; else return empty string.
if (!TryValidateModel(user))
{
return new BadRequestObjectResult(ModelState);
}
return Content(string.Empty);
}
[HttpGet]
public IActionResult GetInvalidAdminWithPrefix()
{
var admin = new Administrator()
{
Id = 1,
Name = "John Doe",
Designation = "Administrator",
AdminAccessCode = 0
};
if (!TryValidateModel(admin,"admin"))
{
return new BadRequestObjectResult(ModelState);
}
return Content(string.Empty);
}
[HttpGet]
public IActionResult GetValidAdminWithPrefix()
{
var admin = new Administrator()
{
Id = 1,
Name = "John Doe",
Designation = "Administrator",
AdminAccessCode = 1
};
if (!TryValidateModel(admin, "admin"))
{
return new BadRequestObjectResult(ModelState);
}
return Content("Admin user created successfully");
}
}
}

View File

@ -1,13 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace FormatterWebSite
{
[AdminValidator]
public class Administrator : User
{
public int AdminAccessCode { get; set; }
}
}

View File

@ -3,17 +3,16 @@
using System.ComponentModel.DataAnnotations;
namespace FormatterWebSite
namespace ValidationWebSite
{
public class AdminValidator : ValidationAttribute
public class CompanyNameAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var admin = (Administrator)value;
if (admin.AdminAccessCode != 1)
var valueString = value as string;
if (string.IsNullOrEmpty(valueString))
{
return new ValidationResult ("AdminAccessCode property does not have the right value");
return new ValidationResult("CompanyName cannot be null or empty.");
}
return null;

View File

@ -0,0 +1,102 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Microsoft.AspNet.Mvc;
using ValidationWebSite.ViewModels;
namespace ValidationWebSite.Controllers
{
public class ModelMetadataTypeValidationController : Controller
{
[HttpPost]
public object ValidateProductViewModelIncludingMetadata([FromBody] ProductViewModel product)
{
return CreateValidationDictionary();
}
[HttpPost]
public object ValidateSoftwareViewModelIncludingMetadata([FromBody] SoftwareViewModel software)
{
return CreateValidationDictionary();
}
[HttpPost]
public object TryValidateModelAfterClearingValidationErrorInParameter(
[Required, MaxLength(3), StringLength(10, MinimumLength = 3)] string theImpossibleString,
[FromBody] ProductViewModel product)
{
// Clear ModelState entry. TryValidateModel should not add entries except those found within the
// passed model.
ModelState["theImpossibleString"].Errors.Clear();
TryValidateModel(product);
return CreateValidationDictionary();
}
[HttpGet]
public object TryValidateModelSoftwareViewModelWithPrefix()
{
var softwareViewModel = new SoftwareViewModel
{
Category = "Technology",
CompanyName = "Microsoft",
Contact = "4258393231",
Country = "UK",
DatePurchased = new DateTime(2010, 10, 10),
Price = 110,
Version = "2"
};
TryValidateModel(softwareViewModel, "software");
return CreateValidationDictionary();
}
[HttpGet]
public object TryValidateModelValidModelNoPrefix()
{
var softwareViewModel = new SoftwareViewModel
{
Category = "Technology",
CompanyName = "Microsoft",
Contact = "4258393231",
Country = "USA",
DatePurchased = new DateTime(2010, 10, 10),
Name = "MVC",
Price = 110,
Version = "2"
};
TryValidateModel(softwareViewModel);
return CreateValidationDictionary();
}
private Dictionary<string, string> CreateValidationDictionary()
{
var result = new Dictionary<string, string>();
foreach (var item in ModelState)
{
var errorMessage = string.Empty;
foreach (var error in item.Value.Errors)
{
if (error != null)
{
errorMessage = errorMessage + error.ErrorMessage;
}
}
if (!string.IsNullOrEmpty(errorMessage))
{
result.Add(item.Key, errorMessage);
}
}
return result;
}
}
}

View File

@ -0,0 +1,30 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.ComponentModel.DataAnnotations;
namespace ValidationWebSite.Models
{
[ProductValidator]
public class Product
{
public string Name { get; set; }
[StringLength(20)]
[RegularExpression("^[0-9]*$")]
[Display(Name = "Contact Us")]
public string Contact { get; set; }
[Range(0, 100)]
public virtual int Price { get; set; }
[CompanyName]
public string CompanyName { get; set; }
public string Country { get; set; }
[Required]
public ProductDetails ProductDetails { get; set; }
}
}

View File

@ -0,0 +1,19 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.ComponentModel.DataAnnotations;
namespace ValidationWebSite.Models
{
public class ProductDetails
{
[Required]
public string Detail1 { get; set; }
[Required]
public string Detail2 { get; set; }
[Required]
public string Detail3 { get; set; }
}
}

View File

@ -0,0 +1,22 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.ComponentModel.DataAnnotations;
namespace ValidationWebSite.Models
{
public class Software : Product
{
public string Version { get; set; }
[Required]
public DateTime DatePurchased { get; set; }
[Range(100, 200)]
public override int Price { get; set; }
[StringLength(10)]
public new string Contact { get; set; }
}
}

View File

@ -0,0 +1,42 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.ComponentModel.DataAnnotations;
using ValidationWebSite.ViewModels;
namespace ValidationWebSite
{
public class ProductValidatorAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var product = value as ProductViewModel;
if (product != null)
{
if (!product.Country.Equals("USA") || string.IsNullOrEmpty(product.Name))
{
return new ValidationResult("Product must be made in the USA if it is not named.");
}
else
{
return null;
}
}
var software = value as SoftwareViewModel;
if (software != null)
{
if (!software.Country.Equals("USA") || string.IsNullOrEmpty(software.Name))
{
return new ValidationResult("Product must be made in the USA if it is not named.");
}
else
{
return null;
}
}
return new ValidationResult("Expected either ProductViewModel or SoftwareViewModel instance but got "
+ value.GetType() + " instance");
}
}
}

View File

@ -0,0 +1,33 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Builder;
using Microsoft.Framework.DependencyInjection;
namespace ValidationWebSite
{
public class Startup
{
public void Configure(IApplicationBuilder app)
{
var configuration = app.GetTestConfiguration();
// Set up application services
app.UseServices(services =>
{
// Add MVC services to the services container
services.AddMvc(configuration);
});
app.UseErrorReporter();
// Add MVC to the request pipeline
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action}/{id?}");
});
}
}
}

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>87ab84b2-22c1-43c6-bb8a-1d327b446fb0</ProjectGuid>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<DevelopmentServerPort>49635</DevelopmentServerPort>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
<ProjectExtensions>
<VisualStudio>
<UserProperties project_1json__JSONSchema="http://www.asp.net/media/4878834/project.json" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@ -0,0 +1,32 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNet.Mvc;
using ValidationWebSite.Models;
namespace ValidationWebSite.ViewModels
{
[ModelMetadataType(typeof(Product))]
public class ProductViewModel
{
public string Name { get; set; }
[Required]
public string Contact { get; set; }
[Range(20, 100)]
public int Price { get; set; }
[RegularExpression("^[a-zA-Z]*$")]
[Required]
public string Category { get; set; }
public string CompanyName { get; set; }
public string Country { get; set; }
public ProductDetails ProductDetails { get; set; }
}
}

View File

@ -0,0 +1,31 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNet.Mvc;
using ValidationWebSite.Models;
namespace ValidationWebSite.ViewModels
{
[ModelMetadataType(typeof(Software))]
public class SoftwareViewModel
{
[RegularExpression("^[0-9]*$")]
public string Version { get; set; }
public DateTime DatePurchased { get; set; }
public int Price { get; set; }
public string Contact { get; set; }
public string Country { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public string CompanyName { get; set; }
}
}

View File

@ -0,0 +1,19 @@
{
"commands": {
"web": "Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:5001",
"kestrel": "Microsoft.AspNet.Hosting --server Kestrel --server.urls http://localhost:5000"
},
"dependencies": {
"Kestrel": "1.0.0-*",
"Microsoft.AspNet.Mvc": "6.0.0-*",
"Microsoft.AspNet.Mvc.TestConfiguration": "1.0.0",
"Microsoft.AspNet.Server.IIS": "1.0.0-*",
"Microsoft.AspNet.Server.WebListener": "1.0.0-*",
"Microsoft.AspNet.StaticFiles": "1.0.0-*"
},
"frameworks": {
"aspnet50": { },
"aspnetcore50": { }
},
"webroot": "wwwroot"
}

Binary file not shown.