dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.19k stars 9.93k forks source link

Json serialization on RegisteredFunction.Invoke doesnot camelCase the properties. #16281

Closed muqeet-khan closed 4 years ago

muqeet-khan commented 6 years ago

Am I missing something or does serialization at RegisteredFunction.Invoke does not camelCase the properties of the args? Is there a reason for it?

from cshtml:

RegisteredFunction.Invoke<bool>("newPerson", new[] { Person });

Where Person has simple properties like:

public string FirstName {get;set;} = "Some First Name";
public string LastName {get;set;} = "Some Last Name";

This is how I am calling from JS:

Blazor.registerFunction('newPerson', (item) => {
    console.log(item);
});

the obj I receive in JS:

{
    FirstName: "Some First Name",
    LastName: "Some Last Name"
}

expected:

{
    firstName: "Some First Name",
    lastName: "Some Last Name"
}

If there is a solution or a workaround for this, I would really appreciate someone pointing me in that direction.

SteveSandersonMS commented 6 years ago

The built-in serializer is designed to be simple and does not have configurable rules for naming, hence Your casing is preserved.

If it’s important to change the case, you could use either a JS or .NET library to do that from either side. Alternatively you can use another JSON serialisation library.

riipah commented 6 years ago

I would just add that the same issue exists with HttpClient (probably because it uses the same serializer). Almost all real-life REST APIs send properties with JavaScript style naming (starting with lowercase letter). Meanwhile, using lowercase property names doesn't match C# naming conventions. So without that conversion, the HttpClient isn't very useful at the moment. I know you can change the serializer, but you'd need to do that for consuming almost every API.

rstropek commented 6 years ago

@riipah Blazor uses .NET's System.Net.Http.HttpClient. JSON serialization and deserialization are separate features. I agree that without changing the property names' casing, C# code in Blazor apps will look unusual. However, this is a feature that a JSON library has to bring to the table. Therefore, I would not say that HttpClient is currently not useful. But I agree, a more powerful JSON library would be helpful. Did you look at aspnet/Blazor#160? It contains some interesting comments regarding size of JSON libraries.

riipah commented 6 years ago

@rstropek sorry I was unclear. Also I'm sorry that I'm complaining without proper suggestions. Yes, you're right it's not a problem in HttpClient by itself, I simply meant that for consuming almost any REST API, you would need to change the serialization library, so it would make sense to have the default as something that can handle that conversion. Json.NET is probably overkill. Since it's a simple matter of changing the first letter of the property name, perhaps the feature could be added to SimpleJson, but seeing that the library was last updated in 2014, not sure there's anyone to accept the pull request... DataContractAttribute support would work too, but I guess that was ruled out because of the reflection?

daniel007 commented 6 years ago

I don't know if this is the proper issue to report my problem.

I have a .NET Standard 1.2 Models project shared across multiple applications (not just Blazor). Properties are defined following C# naming convention, starting with uppercase. When calling PostJsonAsync in Blazor, none of the properties are populated unless I change the properties to lowercase. From what I understand, the issue is with the JSON library. If so, I think this is something that needs to addressed, we shouldn't need to use a separate library for deserializing JSON.

How is it possible that this works for the FlightFinder demo?

LandryDubus commented 6 years ago

I have the same problem.

I use the following code on the client side in Blazor to call my asp.net core API issuing an HTTP POST with JSON Data:

Diffusion diffusion = new Diffusion{
                SendToSFTP = true,
                Paquets = paquets.Where(p => p.Selected).Select(p => p.Name).ToList()
};
Result = await Http.PostJsonAsync<bool>("api/Paquet", diffusion);

And on the server I was forced to use custom deserialization using NewtonSoft.Json like this because Blazor was serializing my model properties using camelCase in JSON (not preserving the case) and the server side was not able to understand it natively:

[HttpPost]
public bool Diffusion([FromBody] JObject data)
{
                var diffusion = data.ToObject<Diffusion>();
SteveSandersonMS commented 6 years ago

@Asshiah That sounds like you have the opposite problem, not the same one :)

Yes, the convention for Blazor's JSON seralizer is to use camelCase by popular demand. So you must either make your API backend accept that format (as you have done so), or use a different JSON serializer and construct your HTTP request manually (not using PostJsonAsync).