<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tony Williams &#187; Serialisation</title>
	<atom:link href="http://blog.tonywilliams.me.uk/tag/serialisation/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.tonywilliams.me.uk</link>
	<description></description>
	<lastBuildDate>Tue, 10 Jan 2012 12:31:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>How to POST JSON data to an Asp.Net MVC 2 app with ValidateAntiForgeryToken</title>
		<link>http://blog.tonywilliams.me.uk/how-to-post-json-data-to-an-asp-net-mvc-2-app-with-validateantiforgerytoken/</link>
		<comments>http://blog.tonywilliams.me.uk/how-to-post-json-data-to-an-asp-net-mvc-2-app-with-validateantiforgerytoken/#comments</comments>
		<pubDate>Fri, 24 Sep 2010 14:34:40 +0000</pubDate>
		<dc:creator>Tony</dc:creator>
				<category><![CDATA[Asp.Net MVC]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[AntiForgeryToken]]></category>
		<category><![CDATA[Asp.Net MVC2]]></category>
		<category><![CDATA[Attribute]]></category>
		<category><![CDATA[Serialisation]]></category>

		<guid isPermaLink="false">http://blog.tonywilliams.me.uk/?p=94</guid>
		<description><![CDATA[All in the title.]]></description>
			<content:encoded><![CDATA[<div>
<p>The title says it all really, earlier this week I was attempting to submit data in the form of JSON to a controller method that implemented the <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.validateantiforgerytokenattribute.aspx">ValidateAntiForgeryTokenAttribute</a>.</p>
<p>On the client side of things  I managed to get the validation input generated by <a href="http://msdn.microsoft.com/en-us/library/dd470175.aspx">Html.AntiForgeryToken</a> into my JSON object but I just kept on getting the <strong>&#8220;A required anti-forgery token was not supplied or was invalid&#8221; </strong>exception.</p>
<p>After a bit of research I found the problem to lie in the <a href="http://aspnet.codeplex.com/">Asp.Net MVC 2 source</a>, if you look at the ValidateAntiForgeryTokenAttribute file specifically on line 56 (OnAuthorization method) you&#8217;ll see this:</p>
<pre class="brush:c#">string formValue = filterContext.HttpContext.Request.Form[fieldName];</pre>
<p>The validation class always checks the form for the token but we don&#8217;t have any form data when we post JSON!</p>
<p>So my solution was to modify like so:</p>
<pre class="brush:c#">      string value;
      if (filterContext.HttpContext.Request.ContentType.ToLower().Contains("json"))
      {
        var bytes = new byte[filterContext.HttpContext.Request.InputStream.Length];
        filterContext.HttpContext.Request.InputStream.Read(bytes, 0, bytes.Length);
        filterContext.HttpContext.Request.InputStream.Position = 0;
        var json = Encoding.ASCII.GetString(bytes);
        var jsonObject = JObject.Parse(json);
        value = (string)jsonObject[fieldName];
      }
      else
      {
        value = filterContext.HttpContext.Request.Form[fieldName];
      }</pre>
<p>What happens here is I do a check to see if the post is json, if so I then pull the string from the input stream and using a <a href="http://sourceforge.net/projects/csjson/">JSON parser</a> extract the token.</p>
<p>Since we&#8217;re modifying the ValidateAntiForgery class we might as allow it to work  with (or restrict to) any http verb.</p>
<p>This is what I&#8217;ve ended up with (sorry about the formatting):</p>
<pre class="brush:c#">namespace Your.App
{
  using System;
  using System.Linq;
  using System.Text;
  using System.Web;
  using System.Web.Mvc;
  using Newtonsoft.Json.Linq;

  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
  public class ValidateJsonAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
  {
    private string _salt;
    private AntiForgeryDataSerializer _serializer;
    private readonly AcceptVerbsAttribute _verbs;

    public string Salt
    {
      get
      {
        return _salt ?? String.Empty;
      }
      set
      {
        _salt = value;
      }
    }

    internal AntiForgeryDataSerializer Serializer
    {
      get
      {
        if (_serializer == null)
        {
          _serializer = new AntiForgeryDataSerializer();
        }
        return _serializer;
      }
      set
      {
        _serializer = value;
      }
    }

    public ValidateJsonAntiForgeryTokenAttribute(HttpVerbs verbs = HttpVerbs.Post):this(null, verbs)
    {
    }

    public ValidateJsonAntiForgeryTokenAttribute(string salt, HttpVerbs verbs = HttpVerbs.Post)
    {
      this._verbs = new AcceptVerbsAttribute(verbs);
      this._salt = salt;
    }

    private bool ValidateFormToken(AntiForgeryData token)
    {
      return (String.Equals(Salt, token.Salt, StringComparison.Ordinal));
    }

    private static HttpAntiForgeryException CreateValidationException()
    {
      return new HttpAntiForgeryException("A required anti-forgery token was not supplied or was invalid.");
    }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
      if (filterContext == null)
      {
        throw new ArgumentNullException("filterContext");
      }

      // We only need to validate this if it's a post
      string httpMethodOverride = filterContext.HttpContext.Request.GetHttpMethodOverride();
      if (!this._verbs.Verbs.Contains(httpMethodOverride, StringComparer.OrdinalIgnoreCase))
      {
        return;
      }

      string fieldName = AntiForgeryData.GetAntiForgeryTokenName(null);
      string cookieName = AntiForgeryData.GetAntiForgeryTokenName(filterContext.HttpContext.Request.ApplicationPath);

      HttpCookie cookie = filterContext.HttpContext.Request.Cookies[cookieName];
      if (cookie == null || String.IsNullOrEmpty(cookie.Value))
      {
        // error: cookie token is missing
        throw CreateValidationException();
      }
      AntiForgeryData cookieToken = Serializer.Deserialize(cookie.Value);

      string value;
      if (filterContext.HttpContext.Request.ContentType.ToLower().Contains("json"))
      {
        var bytes = new byte[filterContext.HttpContext.Request.InputStream.Length];
        filterContext.HttpContext.Request.InputStream.Read(bytes, 0, bytes.Length);
        filterContext.HttpContext.Request.InputStream.Position = 0;
        var json = Encoding.ASCII.GetString(bytes);
        var jsonObject = JObject.Parse(json);
        value = (string)jsonObject[fieldName];
      }
      else
      {
        value = filterContext.HttpContext.Request.Form[fieldName];
      }

      if (String.IsNullOrEmpty(value))
      {
        // error: form token is missing
        throw CreateValidationException();
      }
      AntiForgeryData formToken = Serializer.Deserialize(value);

      if (!String.Equals(cookieToken.Value, formToken.Value, StringComparison.Ordinal))
      {
        // error: form token does not match cookie token
        throw CreateValidationException();
      }

      if (!ValidateFormToken(formToken))
      {
        // error: custom validation failed
        throw CreateValidationException();
      }
    }
  }
}</pre>
<p>Also I had to copy over 2 classes from the MVC source. The &#8220;<em>AntiForgeryData</em>&#8221; and &#8220;<em>AntiForgeryDataSerializer</em>&#8221; since they are interal and my project wouldn&#8217;t compile without them.</p>
<p>Final note, if you&#8217;re having trouble with the Serializer you copied over (in the Deserialize method and casting to a Triplet) then this may be of some help (.Net 4.0 only):</p>
<pre class="brush:c#">                dynamic deserializedObj = formatter.Deserialize(serializedToken);
                return new AntiForgeryData() {
                    Salt = deserializedObj[0],
                    Value = deserializedObj[1],
                    CreationDate = (DateTime)deserializedObj[2]
                };</pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.tonywilliams.me.uk/how-to-post-json-data-to-an-asp-net-mvc-2-app-with-validateantiforgerytoken/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Short Break</title>
		<link>http://blog.tonywilliams.me.uk/short-break/</link>
		<comments>http://blog.tonywilliams.me.uk/short-break/#comments</comments>
		<pubDate>Tue, 24 Aug 2010 13:15:38 +0000</pubDate>
		<dc:creator>Tony</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Attribute]]></category>
		<category><![CDATA[Caching]]></category>
		<category><![CDATA[Enyim]]></category>
		<category><![CDATA[Memcached]]></category>
		<category><![CDATA[Serialisation]]></category>

		<guid isPermaLink="false">http://blog.tonywilliams.me.uk/?p=77</guid>
		<description><![CDATA[Enyim reminder ]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been sometime since I&#8217;ve last posted an update to my blog so I thought I&#8217;d better get in gear and do something about it. So for now here is a reminder for those who use <a href="http://memcached.org/">Memcached </a>with <a href="http://memcached.enyim.com/">Enyim</a>.</p>
<p style="padding-left: 30px;">USE THE <strong><a href="http://msdn.microsoft.com/en-us/library/system.serializableattribute.aspx">[Serializable]</a> </strong>ATTRIBUTE ON YOUR CLASSES.</p>
<p>I keep forgetting that.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tonywilliams.me.uk/short-break/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Serialising / Deserialising objects to Xml in .Net</title>
		<link>http://blog.tonywilliams.me.uk/serialising-deserialising-objects-to-xml-in-net/</link>
		<comments>http://blog.tonywilliams.me.uk/serialising-deserialising-objects-to-xml-in-net/#comments</comments>
		<pubDate>Mon, 12 Jul 2010 08:26:14 +0000</pubDate>
		<dc:creator>Tony</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Extension Methods]]></category>
		<category><![CDATA[Serialisation]]></category>

		<guid isPermaLink="false">http://blog.tonywilliams.me.uk/?p=34</guid>
		<description><![CDATA[Extension method for serialisation of classes to xml]]></description>
			<content:encoded><![CDATA[<p>Serialising / Deserialising objects to Xml: from my <a href="http://stackoverflow.com/questions/271398/what-are-your-favorite-extension-methods-for-c-codeplex-com-extensionoverflow/271423#271423">StackOverFlow</a></p>
<pre class="brush:c#">private static readonly Dictionary&lt;Type, XmlSerializer&gt; serialisers = new Dictionary&lt;Type, XmlSerializer&gt;();

/// &lt;summary&gt;Serialises an object of type T in to an xml string&lt;/summary&gt;
/// &lt;typeparam name="T"&gt;Any class type&lt;/typeparam&gt;
/// &lt;param name="objectToSerialise"&gt;Object to serialise&lt;/param&gt;
/// &lt;returns&gt;A string that represents Xml, empty oterwise&lt;/returns&gt;
public static string XmlSerialise&lt;T&gt;(this T objectToSerialise) where T : class, new()
{
  XmlSerializer serialiser;

  var type = typeof(T);
  if (!serialisers.ContainsKey(type))
  {
    serialiser = new XmlSerializer(type);
    serialisers.Add(type, serialiser);
  }
  else
  {
    serialiser = serialisers[type];
  }

  string xml;
  using (var writer = new StringWriter())
  {
    serialiser.Serialize(writer, objectToSerialise);
    xml = writer.ToString();
  }

  return xml;
}

/// &lt;summary&gt;Deserialises an xml string in to an object of Type T&lt;/summary&gt;
/// &lt;typeparam name="T"&gt;Any class type&lt;/typeparam&gt;
/// &lt;param name="xml"&gt;Xml as string to deserialise from&lt;/param&gt;
/// &lt;returns&gt;A new object of type T is successful, null if failed&lt;/returns&gt;
public static T XmlDeserialise&lt;T&gt;(this string xml) where T : class, new()
{
  XmlSerializer serialiser;

  var type = typeof(T);
  if (!serialisers.ContainsKey(type))
  {
    serialiser = new XmlSerializer(type);
    serialisers.Add(type, serialiser);
  }
  else
  {
    serialiser = serialisers[type];
  }

  T newObject;

  using (var reader = new StringReader(xml))
  {
    try { newObject = (T)serialiser.Deserialize(reader); }
    catch { return null; } // Could not be deserialized to this type.
  }

  return newObject;
}</pre>
<p>When building the serialisation I had a help from an online example &#8211; but cannot remeber where it is&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tonywilliams.me.uk/serialising-deserialising-objects-to-xml-in-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

