Dynamic Deserialization using JsonConverter

This post is the continuation from the previous post. The previous post was in regard to casting the object dynamically. This post will explain how to deserialize dynamically from Json object

I have a json that I want to deserialize dynamically based on a specific property that defines what object it is. We can do it easily and elegantly by using JsonConverter

1. Create a custom JsonConverter

public class MessageConverter : JsonConverter
    {
        static readonly JsonSerializerSettings SpecifiedSubclassConversion = new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() };

        public override bool CanConvert(Type objectType)
        {
            return (objectType == typeof(WhafflMetadata));
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var jObject = JObject.Load(reader);

            switch (jObject["messageType"].Value<string>())
            {
                case "STAFF_CREATED":
                    return JsonConvert.DeserializeObject<Message<StaffDetail>>(jObject.ToString(), SpecifiedSubclassConversion);

                case "CITY_CREATED":
                    return JsonConvert.DeserializeObject<Message<City>>(jObject.ToString(), SpecifiedSubclassConversion);

                default:
                    throw new Exception(string.Format("messageType {0} cannot be handled", jObject["messageType"].Value<string>()));
            }
        }

        public override bool CanWrite
        {
            get { return false; }
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }

2. Cast it using your converter

JsonConvert.DeserializeObject<Message>(
                jsonValue,
                new JsonSerializerSettings { Converters = new JsonConverter[] { new MessageConverter() } });

401 Unauthorized – WebRequest

I got this nasty 401 unauthorized error from my code all of sudden, I don’t really know why and what’s causing it. I used Fiddler as a proxy to see the request header and all of sudden it works but then removing the proxy again brings back the 401!!!

So after googling for a while i found something interesting about browser was requesting for authentication level etc therefore even if you pass the basic security header then it will just simply ignore it. So I played around with the code below and it fixes my issue

WebRequest request = WebRequest.Create(source);
request.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequested;

Action Filter in WebApi 2

Its been a while I haven’t blogged for sometime. To create an action filter in Web Api 2 and return the response directly you can use the code below

public class StepUpAttribute : ActionFilterAttribute
{
public IUserFactory CurrentUser { get; set; }

public override void OnActionExecuting(HttpActionContext filterContext)
{
if (CurrentUser.IsSteppedUp)
return;

// stop request process and return
filterContext.Response = filterContext.Request.CreateResponse(HttpStatusCode.OK,
ErrorResponseFactory.FromUnsafeActionDetectedResponse(),
filterContext.ControllerContext.Configuration.Formatters.JsonFormatter);

}
}

Exporting Excel to XML: A mapped element’s relationship with other elements cannot be preserved

I have an Excel file that need to be exported into XML. I have a few files to be converted. One of them was complaining when I’m about to export it to XML and it throws an error of "A mapped element’s relationship with other elements cannot be preserved". Spend quite a few hours try to google it out and fix it but with no luck. So what I did to resolve this issue "Convert the excel into CSV and then open the CSV with Excel and applied my XSD and export it to XML again and it works fine!!"

Remove Folder on the Release Mode using MSBuild

I got this code snippet to remove "TestHarness" folder only on the Release Mode but when I publish it on the "Debug" Mode the folder should still be there. It is a simple code but it took me a while to figure it out

My csproj file

<ItemGroup>
<ExcludeFromPackageFolders Include="TestHarness" Condition=" ‘$(Configuration)’ == ‘Release’">
<FromTarget>Project</FromTarget>
</ExcludeFromPackageFolders>
</ItemGroup>

Fusion Log – Assembly Logging

Another helpful debugging tool that can be used is FusionLog – it is already installed in your machine by default and what this tool does is basically logging and telling us where the assembly is loaded from either local or GAC or some other location and at the same time it tells you it couldn’t locate the assembly

-First create a folder called “FusionLog” on C drive or any location with any name

-Open your Regedit to add the key below

HKEY_LOCAL_MACHINESOFTWAREMicrosoftFusion

Add:

DWORD ForceLog set value to 1

DWORD LogFailures set value to 1

DWORD LogResourceBinds set value to 1

String LogPath set value to folder for logs (e.g. C:FusionLog)

Make sure you include the backslash after the folder name and that the Folder exists.

-Restart your computer

-Run your application

-Look the assembly name from c:fusionlog

-Open the file and it will tell you where the assembly is loaded from

Table Valued Parameter – SQL Server 2008

Simple sample in how to use Table Valued Parameter which is a new feature in SQL Server 2008. I found it very useful to pass bulk data from one SP to another SP

CREATE TYPE JobQueueBroker AS TABLE (JobID INT NOT NULL, UpdateDate DATETIME DEFAULT(GETDATE()))
GO

CREATE PROCEDURE [dbo].[Jobs_JobX_SubmitQueueBulk]
@Jobs JobQueueBroker READONLY
AS

BEGIN
DECLARE @Message XML

SELECT @Message = ( SELECT * FROM @Jobs
FOR XML PATH(‘Job’),
TYPE
);

— Above will fomulate valid XML message
DECLARE @Handle UNIQUEIDENTIFIER ;

— Dialog Conversation starts here
BEGIN DIALOG CONVERSATION @Handle FROM SERVICE ServiceJobXJobFinishedProcessing TO SERVICE ‘ServiceJobXJobUpdate’ ON CONTRACT [JobContract] WITH ENCRYPTION = OFF ;
SEND ON CONVERSATION @Handle MESSAGE TYPE JobDetails (@Message) ;

END
GO

DECLARE @Jobs JobQueueBroker
INSERT @Jobs VALUES (1, GETDATE())
INSERT @Jobs VALUES (2, GETDATE())
INSERT @Jobs VALUES (3, GETDATE())
EXEC dbo.[Jobs_JobX_SubmitQueueBulk] @Jobs
GO