Permalink
Browse files

Configured MVC to use JsonCamelCaseFormatter for WebApi.

* I create WebCommon project to put web-related reusable code here.
* I added JsonCamelCaseFormatter.cs to this project.  This formatter will generate JSON objects with property names following camelcase convention.
* I added a nuget to Json.net in order to code up JsonCamelCaseFormatter.
* In Global.asax.cs, I configured MVC to use JsonCamelCaseFormatter.
* I create WebApiTestController to test out the JsonCamelCaseFormatter.  This /public/WebApiTest/Index  will make an ajax call to PersonApiController, which will return a person object.  The person object will be serialized using JsonCamelCaseFormatter to the browser.
  • Loading branch information...
ptran123 committed Apr 19, 2012
1 parent 64bc354 commit a66e9c72ed7d63a183e3509910f56dc10f9f2bec
Showing with 49,722 additions and 8 deletions.
  1. BIN MvcCodeFirstSolution/MvcCodeFirst/App_Data/CodeFirst.sdf
  2. +15 −0 MvcCodeFirstSolution/MvcCodeFirst/Areas/Public/Views/WebApiTest/Index.cshtml
  3. +1 −1 MvcCodeFirstSolution/MvcCodeFirst/Areas/Shared/_Layout.cshtml
  4. +14 −6 MvcCodeFirstSolution/MvcCodeFirst/Global.asax.cs
  5. +9 −1 MvcCodeFirstSolution/MvcCodeFirst/MvcCodeFirst.csproj
  6. +10 −0 MvcCodeFirstSolution/MvcCodeFirstSolution.sln
  7. +31 −0 MvcCodeFirstSolution/PublicArea/Controllers/PersonApiController.cs
  8. +12 −0 MvcCodeFirstSolution/PublicArea/Controllers/WebApiTestController.cs
  9. +33 −0 MvcCodeFirstSolution/PublicArea/PublicArea.csproj
  10. +9 −0 MvcCodeFirstSolution/PublicArea/packages.config
  11. +68 −0 MvcCodeFirstSolution/WebCommon/JsonCamelCaseFormatter.cs
  12. +36 −0 MvcCodeFirstSolution/WebCommon/Properties/AssemblyInfo.cs
  13. +65 −0 MvcCodeFirstSolution/WebCommon/WebCommon.csproj
  14. +4 −0 MvcCodeFirstSolution/WebCommon/packages.config
  15. BIN MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/Newtonsoft.Json.4.5.3.nupkg
  16. BIN MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/net20/Newtonsoft.Json.dll
  17. BIN MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/net20/Newtonsoft.Json.pdb
  18. +7,969 −0 MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/net20/Newtonsoft.Json.xml
  19. BIN MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/net35/Newtonsoft.Json.dll
  20. BIN MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/net35/Newtonsoft.Json.pdb
  21. +7,100 −0 MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/net35/Newtonsoft.Json.xml
  22. BIN MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/net40/Newtonsoft.Json.dll
  23. BIN MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/net40/Newtonsoft.Json.pdb
  24. +7,343 −0 MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/net40/Newtonsoft.Json.xml
  25. BIN MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/sl3-wp/Newtonsoft.Json.dll
  26. BIN MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/sl3-wp/Newtonsoft.Json.pdb
  27. +6,684 −0 MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/sl3-wp/Newtonsoft.Json.xml
  28. BIN MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/sl4-windowsphone71/Newtonsoft.Json.dll
  29. BIN MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/sl4-windowsphone71/Newtonsoft.Json.pdb
  30. +6,684 −0 MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/sl4-windowsphone71/Newtonsoft.Json.xml
  31. BIN MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/sl4/Newtonsoft.Json.dll
  32. BIN MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/sl4/Newtonsoft.Json.pdb
  33. +6,706 −0 MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/sl4/Newtonsoft.Json.xml
  34. BIN MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/winrt45/Newtonsoft.Json.dll
  35. BIN MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/winrt45/Newtonsoft.Json.pdb
  36. +6,927 −0 MvcCodeFirstSolution/packages/Newtonsoft.Json.4.5.3/lib/winrt45/Newtonsoft.Json.xml
  37. +2 −0 MvcCodeFirstSolution/packages/repositories.config
Binary file not shown.
@@ -0,0 +1,15 @@
+@using (Html.BeginForm())
+{
+ <input id="b1" type="button" value="click" />
+}
+@section javascript {
+ <script type="text/javascript">
+ $(function () {
+ $("#b1").click(function () {
+ $.get("/api/PersonApi/123", function (person) {
+ alert(person.firstName + " " + person.lastName);
+ });
+ });
+ });
+ </script>
+}
@@ -22,7 +22,7 @@
<script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.7/jquery.validate.min.js"></script>
<script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.min.js"></script>
- <script type="text/javascript" src="@Url.Content("~/Javascript/Validation.Callout.js")"></script>
+ <script type="text/javascript" src="~/Javascript/Validation.Callout.js"></script>
<script type="text/javascript">
window.jQuery || document.write('<script src="~/Scripts/jquery-1.7.1.min.js"><\/script>');
window.jQuery.validator || document.write('<script src="~/Scripts/jquery.validate.min.js"><\/script>');
@@ -1,11 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using System.Web.Http;
+using System.Web.Http;
using System.Web.Mvc;
-using System.Web.Optimization;
using System.Web.Routing;
+using WebCommon;
namespace MvcCodeFirst
{
@@ -56,6 +52,18 @@ protected void Application_Start()
// ref: http://blogs.msdn.com/b/marcinon/archive/2011/08/16/optimizing-mvc-view-lookup-performance.aspx
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new RazorViewEngine());
+
+
+ RegistersonFormatterForWebApi();
+ }
+
+ private void RegistersonFormatterForWebApi()
+ {
+ // Replace the default JsonFormatter with our custom one. Note: config.Formatters.JsonFormatter is only by webapi.
+ // So, controllers that return a JsonResult will not use JsonCamelCaseFormatter below.
+ var config = GlobalConfiguration.Configuration;
+ var index = config.Formatters.IndexOf(config.Formatters.JsonFormatter);
+ config.Formatters[index] = new JsonCamelCaseFormatter();
}
}
}
@@ -121,6 +121,9 @@
<Reference Include="WebActivator, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\WebActivator.1.5\lib\net40\WebActivator.dll</HintPath>
</Reference>
+ <Reference Include="WebCommon">
+ <HintPath>..\GlobalBin\WebCommon.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Global.asax.cs">
@@ -234,7 +237,9 @@
<Content Include="Areas\Public\Views\Home\Index.cshtml" />
<Content Include="Areas\Public\Views\Product\Detail.cshtml" />
<Content Include="Areas\Public\Views\Product\Index.cshtml" />
- <Content Include="Areas\Public\Views\Web.config" />
+ <Content Include="Areas\Public\Views\Web.config">
+ <SubType>Designer</SubType>
+ </Content>
<Content Include="Areas\Public\Views\_ViewStart.cshtml" />
<Content Include="Areas\Shared\Error.cshtml" />
<Content Include="Areas\Shared\_Layout.cshtml" />
@@ -243,6 +248,9 @@
<Content Include="Areas\Web.config" />
<Content Include="Areas\_ViewStart.cshtml" />
</ItemGroup>
+ <ItemGroup>
+ <Content Include="Areas\Public\Views\WebApiTest\Index.cshtml" />
+ </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
@@ -28,6 +28,11 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure", "Infrastructure\Infrastructure.csproj", "{AEC285EE-D051-4FBC-9127-6B1E620DA43E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MvcCodeFirst", "MvcCodeFirst\MvcCodeFirst.csproj", "{D3AAF987-8559-4E7E-BDC6-CF13A6A96148}"
+ ProjectSection(ProjectDependencies) = postProject
+ {A0180CF8-AAD3-4332-B9C9-3E3F59493148} = {A0180CF8-AAD3-4332-B9C9-3E3F59493148}
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebCommon", "WebCommon\WebCommon.csproj", "{A0180CF8-AAD3-4332-B9C9-3E3F59493148}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -67,6 +72,10 @@ Global
{D3AAF987-8559-4E7E-BDC6-CF13A6A96148}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D3AAF987-8559-4E7E-BDC6-CF13A6A96148}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D3AAF987-8559-4E7E-BDC6-CF13A6A96148}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A0180CF8-AAD3-4332-B9C9-3E3F59493148}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A0180CF8-AAD3-4332-B9C9-3E3F59493148}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A0180CF8-AAD3-4332-B9C9-3E3F59493148}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A0180CF8-AAD3-4332-B9C9-3E3F59493148}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -75,6 +84,7 @@ Global
{5BD5DB1D-D803-4F03-89A7-E7E4CEC50EB1} = {9B5F10B0-7942-4237-A9A9-71DB7ED28CCC}
{74954052-89EB-4D3E-AC35-4A3A86A15F63} = {9B5F10B0-7942-4237-A9A9-71DB7ED28CCC}
{187991FC-ED62-4293-BC58-AF3FAAFD76B4} = {9B5F10B0-7942-4237-A9A9-71DB7ED28CCC}
+ {A0180CF8-AAD3-4332-B9C9-3E3F59493148} = {9B5F10B0-7942-4237-A9A9-71DB7ED28CCC}
{F7ECE494-CCFE-4F07-A0BE-D72760C63C67} = {1A056DBE-6A99-4866-B2D0-96C9321FA35A}
{6B418607-C2A9-4465-A148-92BC7250F9D1} = {1A056DBE-6A99-4866-B2D0-96C9321FA35A}
EndGlobalSection
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using System.Web.Http;
+
+namespace PublicArea.Controllers.Controllers
+{
+ public class PersonApiController : ApiController
+ {
+ /// <summary>
+ /// This example demonstrates how we can use JsonCamelCaseFormatter (configured in Global.asax) to return to the browser an
+ /// object literal where object properties names are generated using camel-case convention.
+ /// </summary>
+ /// <param name="id"></param>
+ /// <returns></returns>
+ public Person Get(int id)
+ {
+ var person = new Person
+ {
+ FirstName = "Peter",
+ LastName = "Tran"
+ };
+ return person;
+ }
+
+ }
+
+ public class Person
+ {
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+ }
+}
@@ -0,0 +1,12 @@
+using System.Web.Mvc;
+
+namespace PublicArea.Controllers
+{
+ public class WebApiTestController : Controller
+ {
+ public ActionResult Index()
+ {
+ return View();
+ }
+ }
+}
@@ -39,7 +39,35 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
+ <Reference Include="System.Json, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\System.Json.4.0.20126.16343\lib\net40\System.Json.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Net.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\System.Net.Http.2.0.20126.16343\lib\net40\System.Net.Http.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\System.Net.Http.Formatting.4.0.20126.16343\lib\net40\System.Net.Http.Formatting.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Net.Http.WebRequest, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\System.Net.Http.2.0.20126.16343\lib\net40\System.Net.Http.WebRequest.dll</HintPath>
+ </Reference>
<Reference Include="System.Web" />
+ <Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\AspNetWebApi.Core.4.0.20126.16343\lib\net40\System.Web.Http.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Web.Http.Common, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\System.Web.Http.Common.4.0.20126.16343\lib\net40\System.Web.Http.Common.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\AspNetWebApi.4.0.20126.16343\lib\net40\System.Web.Http.WebHost.dll</HintPath>
+ </Reference>
<Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\AspNetMvc.4.0.20126.16343\lib\net40\System.Web.Mvc.dll</HintPath>
@@ -49,10 +77,15 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Controllers\HomeController.cs" />
+ <Compile Include="Controllers\PersonApiController.cs" />
<Compile Include="Controllers\ProductController.cs" />
+ <Compile Include="Controllers\WebApiTestController.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PublicAreaRegistration.cs" />
</ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="AspNetWebApi" version="4.0.20126.16343" />
+ <package id="AspNetWebApi.Core" version="4.0.20126.16343" />
+ <package id="System.Json" version="4.0.20126.16343" />
+ <package id="System.Net.Http" version="2.0.20126.16343" />
+ <package id="System.Net.Http.Formatting" version="4.0.20126.16343" />
+ <package id="System.Web.Http.Common" version="4.0.20126.16343" />
+</packages>
@@ -0,0 +1,68 @@
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Http.Formatting;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+
+namespace WebCommon
+{
+ /// <summary>
+ /// ref: http://blogs.msdn.com/b/henrikn/archive/2012/02/18/using-json-net-with-asp-net-web-api.aspx
+ /// </summary>
+ public class JsonCamelCaseFormatter : MediaTypeFormatter
+ {
+ private readonly JsonSerializerSettings jsonSerializerSettings;
+
+ public JsonCamelCaseFormatter()
+ {
+ jsonSerializerSettings = new JsonSerializerSettings
+ {
+ ContractResolver = new CamelCasePropertyNamesContractResolver()
+ };
+
+ // Fill out the mediatype and encoding we support
+ SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
+ Encoding = new UTF8Encoding(false, true);
+ }
+
+ protected override bool CanReadType(Type type)
+ {
+ return type != typeof(IKeyValueModel);
+ }
+
+ protected override bool CanWriteType(Type type)
+ {
+ return true;
+ }
+
+ protected override Task<object> OnReadFromStreamAsync(Type type, Stream stream, HttpContentHeaders contentHeaders, FormatterContext formatterContext)
+ {
+ var serializer = JsonSerializer.Create(jsonSerializerSettings);
+
+ return Task.Factory.StartNew(() =>
+ {
+ using (var streamReader = new StreamReader(stream, Encoding))
+ using (var jsonTextReader = new JsonTextReader(streamReader))
+ return serializer.Deserialize(jsonTextReader, type);
+ });
+ }
+
+ protected override Task OnWriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, FormatterContext formatterContext, TransportContext transportContext)
+ {
+ var serializer = JsonSerializer.Create(jsonSerializerSettings);
+
+ return Task.Factory.StartNew(() =>
+ {
+ using (var jsonTextWriter = new JsonTextWriter(new StreamWriter(stream, Encoding)) { Formatting = Formatting.Indented, CloseOutput = false })
+ {
+ serializer.Serialize(jsonTextWriter, value);
+ jsonTextWriter.Flush();
+ }
+ });
+ }
+ }
+}
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("WebCommon")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("WebCommon")]
+[assembly: AssemblyCopyright("Copyright © 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("186f679b-85e4-4518-9fd0-caaef9b3d614")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
Oops, something went wrong.

0 comments on commit a66e9c7

Please sign in to comment.