3

When using Angular JS to post back to the server with a complex object the datetime and datetime? values do not bind correctly. I have tried JSON.stringify to no avail. I have posted a related question though possibly it was too general. What I really need to know is how to correctly pass those dates in. What I am currently doing is using workaround in js to convert the dates but I would rather not do that and simply get the dates in the form I need them when in Angular and then pass back the correct values.

How do you bind to those datetime/datetime? values correctly? Please see the following code example and Fiddler post results.

C# Class:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
    public DateTime? ApprovedForSomething { get; set; }
}

Angular JS Controller:

function PersonController($scope, $http) {
    $scope.getPerson = function () {
        $http.get('../../Home/GetPerson/1').success(function (data) {
            $scope.Person = data;
        });
    }
    $scope.updateApprovedForSomething = function () {
        $http.post('../../Home/UpdatePerson', { person: $scope.Person }).success(function (data) {
            console.log(data);
        });
    }
}

Fiddler Post:

HTTP/1.1 200 OK Cache-Control: private Content-Type: application/json; charset=utf-8 Server: Microsoft-IIS/8.0 X-AspNetMvc-Version: 4.0 X-AspNet-Version: 4.0.30319 X-SourceFiles: =?UTF-8?B?YzpcdXNlcnNcbmlja1xkb2N1bWVudHNcdmlzdWFsIHN0dWRpbyAyMDEyXFByb2plY3RzXFZhbGlkYXRpb25UZXN0XEhvbWVcR2V0UGVyc29uXDE=?= X-Powered-By: ASP.NET Date: Wed, 16 Jan 2013 14:48:34 GMT Content-Length: 124

{"FirstName":"Bob","LastName":"Smith","BirthDate":"/Date(695573315098)/","ApprovedForSomething":"/Date(1358261315098)/"}

This is the result on the server side. The datetime binds to a new datetime value which is not correct and the datetime? is null.

enter image description here

2 Answers 2

3

If someone has better solution then please feel free to update the answer.

There might be better solution out there but what I did is very simple workaround. Just create an encapsulation property for DateTime object to string and use that for binding purpose.

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
    public DateTime? ApprovedForSomething { get; set; }
    public DateTime BirthDateAsString 
    {
        get { return BirthDate.ToShortDateString();}
        set { DateTime.Parse(value, BirthDate);}
   }
}

Over http all objects are treated as strings and but ASP.NET is smart enough to provide Model Binding feature. However it is unable to bind the JavaScript Date object to .NET DateTime object.

Sign up to request clarification or add additional context in comments.

1 Comment

Hi @Jigar, I appreciate your post. I have to admit I was hoping for an answer that would facilitate a 'set it and forget it' approach in other words something that was not so manual however since you are the only one that replied and I have used this approach as well and know it to work I am marking yours as the answer. Thanks for your input.
2

More more robust approach is to use a model binder to work with all incoming dates.

public class DateTimeBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var name = bindingContext.ModelName;
        var value = bindingContext.ValueProvider.GetValue(name);
        if (value == null) 
            return null;

        DateTime date;
        if (DateTime.TryParse(value.AttemptedValue, null, DateTimeStyles.RoundtripKind, out date))
            return date;
        else
            return base.BindModel(controllerContext, bindingContext);
    }
}

Add in the global ASAX.

var dateTimeBinder = new DateTimeBinder();

ModelBinders.Binders.Add(typeof(DateTime), dateTimeBinder);
ModelBinders.Binders.Add(typeof(DateTime?), dateTimeBinder);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.