1

I have an Action in Controller which has an argument of type Class1

[HttpPost]
public IActionResult Create(Class1 c)
{
}

I send data to it using JQuery's Ajax function.

I would like to write my own code to deserialize SampleProperty:

class Class1
{
    public string SampleProperty { get; set; }
}

Is it possible? I would like to override default deserialization.

I've tried many things, for example writing converter:

public class SamplePropertyConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(string);
    }

    public override object ReadJson(JsonReader reader, Type objectType,
                                    object existingValue, JsonSerializer serializer)
    {
        if ((string)existingValue == "abc")
            return "abc123";
        else
            return existingValue;
    }

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

    public override bool CanWrite => false;
    public override bool CanRead => true;
}

and then using it like this:

class Class1
{
    [JsonConverter(typeof(SamplePropertyConverter))]
    public string SampleProperty { get; set; }
}

but in such case SamplePropertyConverter is not used at all. I also tried to add it in Startup, but then I see that it enters CanConvert method, but only for some other requests, not sending Class1 to Create Action.

psur
  • 4,400
  • 26
  • 36
  • 2
    I think you need to explicitly use `[FromBody]` in [tag:asp.net-core], and then post the `Class1` data as JSON in the request body. If the request data is `x-www-form-urlencoded` then the JSON converter will not be used. See: [Confused with FromBody in ASP.NET Core](https://stackoverflow.com/q/50771647/3744182). – dbc Aug 19 '19 at 18:41
  • Also, your `ReadJson()` has a bug. The `existingValue` is the current value of `Class1.SimpleProperty` as it is being deserialized (e.g. as it has been set in the constructor), *not* the value being read. See: [Json.Net Is converting on its own before using my JsonConverter](https://stackoverflow.com/a/32018194/3744182). – dbc Aug 19 '19 at 18:54
  • 1
    @dbc Thanks a lot for hint with `[FromBody]` and `contentType: 'application/json; charset=utf-8'`. Then `JsonConverter` started to be called! But to achieve this I also needed to `JSON.stringify` my object because JQuery haven't converted it automatically to Json, it was still written like for `x-www-form-urlencoded`. – psur Aug 20 '19 at 08:27

1 Answers1

2

If you do not use json, you could use custom model binding to make it.

1.Assume you have ajax code:

 var data = { "SampleProperty": "abc"};
   $(document).ready(function () {
        $.ajax({
            url: '/Test/Create',
            type: 'POST',
            data: data,
            success: function () {

            }

        });
   });

2.Controller:

[HttpPost]
public IActionResult Create(Class1 c)
{
}

3.Class1.cs:

class Class1
{
    [ModelBinder(BinderType = typeof(TestModelBinder))]
    public string SampleProperty { get; set; }
}

4.TestModelBinder.cs

public class TestModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
            throw new ArgumentNullException(nameof(bindingContext));
        var values = bindingContext.ValueProvider.GetValue("SampleProperty");

        string result = "";

        if (values.FirstValue == "abc")
        {
            result = "abc123";
        }else
        {
            result = values.FirstValue;
        }
        bindingContext.Result = ModelBindingResult.Success(result);
        return Task.CompletedTask;
    }
}
Ryan
  • 19,118
  • 10
  • 37
  • 53