1

I admit, I'm confused:

I'm trying to return a simple object that I've converted to JSON as follows:

 viewModel.updateCoder = function (coder) {
   var coderJson = ko.toJSON(coder);
   var coderJsonString = ko.utils.stringifyJson(coderJson);
   $.ajax({
     url: "provider/UpdateCoder",
     type: 'POST',
     dataType: 'text',
     data: coderJsonString,
     contentType: 'text/csv',
     success: function () { alert("Updated!"); }
   });

My RouteTable entry looks like this:

 routes.MapRoute(
    "UpdateCoder",
      "provider/UpdateCoder/{coderDTO}", // URL with parameters
    new { controller = "Provider", action = "UpdateCoder", coderDTO = UrlParameter.Optional }
    );

my Controler action looks like this:

[AcceptVerbs(HttpVerbs.Post)]
public string UpdateCoder( string coderDTO )
{
  var rslt = "success";
  //var coder = coderDTO.CoderDTOToCoder();
  return rslt;
}

What I get in the UpdateCoder parameter ( string coderDTO ) is a null;

This is my fall-back position I'd rather send a JSON object (the coderJson) to the action but I get an error: "No parameterless constructor defined for this object." When I do that I'm changing the parameter type as follows:

[AcceptVerbs(HttpVerbs.Post)]
public string UpdateCoder( **CoderDTO coderDTO** )
{
  var rslt = "success";
  //var coder = coderDTO.CoderDTOToCoder();
  return rslt;
}

along with: ValueProviderFactories.Factories.Add(new JsonValueProviderFactory()); in the Global.asax

the CoderDTO class looks like this:

public class CoderDTO
{
    public Int32 Id { get; set; }
    public String CoderCode { get; set; }
    public String Sal { get; set; }
    public String LName { get; set; }
    public String FName { get; set; }
    public String MI { get; set; }
    public String Facility { get; set; }
    public String Title { get; set; }
    public Boolean? IsContract { get; set; }
    public Boolean? IsInactive { get; set; }
    public Boolean? IsDeleted { get; set; }
    public String Comments { get; set; }
    public String AlternateId { get; set; }
    public int CasesCoded { get; set; }

    public CoderDTO(Coder coder)
    {
        Id = coder.Id;
        CoderCode = coder.CoderCode;
        Sal = coder.Sal;
        LName = coder.LName;
        FName = coder.FName;
        MI = coder.MI;
        Facility = coder.Facility;
        Title = coder.Title;
        if (coder.IsContract != null) IsContract = coder.IsContract;
        if (coder.IsInactive != null) IsInactive = coder.IsInactive;
        if (coder.IsDeleted != null) IsDeleted = coder.IsDeleted;
        Comments = coder.Comments;
        AlternateId = coder.AlternateId;
    }

    public Coder CoderDTOToCoder()
    {
        var coder = new Coder
                    {
                        Id = Id,
                        CoderCode = CoderCode,
                        Sal = Sal,
                        LName = LName,
                        FName = FName,
                        MI = MI,
                        Facility = Facility,
                        Title = Title
                    };
        coder.IsContract = IsContract ?? false;
        coder.IsInactive = IsInactive ?? false;
        coder.IsDeleted = IsDeleted ?? false;
        coder.Comments = Comments;
        coder.AlternateId = AlternateId;
        return coder;
    }


}

The coderJsonString looks like this:

{"Id":201,"CoderCode":"GP ","Sal":null,"LName":null,"FName":null,"MI":null,"IsContract":false,"IsInactive":false,"Comments":null,"CasesCoded":0,"isBeingEdited":false}

It's been a long day!! Thanks for any help, I'm having dinner!!

tereško
  • 58,060
  • 25
  • 98
  • 150
Weej
  • 1,012
  • 2
  • 8
  • 24
  • could you include the dto object along with a sample snippet of the JSON you're posting to the controller? – Jesse Jun 23 '11 at 21:36

3 Answers3

1

I found the answer to the question of why I can't return a JSON that deserializes to my CoderDTO object: My object did not have a parameterless public constructor. I had a constructor parameter of a Coder which populated the CoderDTO. I split that off into a separate method and that now works.

Thanks to a post by

StackOverflow - ASP.NET MVC 3 JSONP: Does this work with JsonValueProviderFactory?

Community
  • 1
  • 1
Weej
  • 1,012
  • 2
  • 8
  • 24
0

I think that your best bet is trying to figure out why you can't deserialize to your DTO. You will need to at least add a default constructor to it.

public CoderDTO() { }

For your current situation with passing strings, I think that you would want to call it like:

viewModel.updateCoder = function (coder) {
   var coderJson = ko.toJSON(coder);
   var coderJsonString = ko.utils.stringifyJson({ coderDTO: coderJson });
   $.ajax({
     url: "provider/UpdateCoder",
     type: 'POST',
     dataType: 'text',
     data: coderJsonString,
     contentType: 'application/json; charset=utf-8',
     success: function () { alert("Updated!"); }
   });

So, basically you create an object with the parameter name and value and stringify it. The coderJson is double-encoded in this case.

RP Niemeyer
  • 114,592
  • 18
  • 291
  • 211
  • RP, thanks, it worked for the string value. I actually tried doing that (including {coderDTO: coderJson} and it didn't work. Maybe it was some other setting that was not correct perhaps in the route?? But, it's confusing: why have a dataType AND a contentType? I'm simply receiving a string, why does 'application/json' work? Does it care if I send a string that doesn't look like json? Maybe it was going for dinner and clearing my head :-). Anyway, now on to how to parse the stringified Json, or better still to simply receive the CoderDTO directly. -- thanks again! – Weej Jun 24 '11 at 01:20
  • Just FYI, the `dataType` describes what you expect to receive back, while the `contentType` describes what you are sending. The JsonValueProvider kicks in when it sees that the content type that it receives is JSON. In this case you are sending an object that has coderDTO set to a string and it is matching it up with your param. Happy to help, if you have more details about your current status. Ideally, you will want to receive your object directly in your action (you will want the contentType to be json as well). – RP Niemeyer Jun 24 '11 at 02:04
  • That's really helpful information. So often I copy/paste bits of code under time pressure (or laziness), kind of praying it'll work. Hence my pain & suffering :-). Armed with this info perhaps I can put this puzzle together. -- Lou – Weej Jun 24 '11 at 11:06
0

Try changing your action to use JsonResult:

[AcceptVerbs(HttpVerbs.Post)]
public JsonResult UpdateCoder(CoderDTO coderDTO)
{
    var rslt = "success";
    //var coder = coderDTO.CoderDTOToCoder();
    return Json(rslt);
}
duyker
  • 800
  • 9
  • 17
  • Thanks duyker, you've got your eye on my real target. I'll try that but my feeling is that the return type is not going to affect the parameter that's received. – Weej Jun 24 '11 at 11:09