Breeze / breeze.server.net

Breeze support for .NET servers
MIT License
76 stars 62 forks source link

Aspnet Core version Affect all my return of webapi with $type and $id #49

Closed badre429 closed 2 years ago

badre429 commented 7 years ago

i am using aspnet core over EF6 the breeze api affect all return values my other webapi with $type and $id

randellhodges commented 7 years ago

It would be nice if you could decorate a specific method or class with a method to adjust the serializer settings. This would contain it to the specific controller/function and would also be a bit more self documenting in the process.

I didn't originally understand the issue badre429 was describing until I figured out how to get my serializer stuff working. I can see his point now.

hankor commented 7 years ago

Haven't tried in combination with EF yet but I think this would be a workaround:

public class BreezeJsonSettingsAttribute : Attribute, IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context)
    {
        var settings = JsonSerializerSettingsProvider.CreateSerializerSettings();
        JsonSerializationFns.UpdateWithDefaults(settings);
        context.Result = new JsonResult(((ObjectResult)context.Result).Value, settings);
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
    }
}

Then decorate method with

[BreezeQueryFilter(Order = 1)]
[BreezeJsonSettings]
khuzemakanore commented 7 years ago

The above code by hankor does not work. Any other solutions?

enkodellc commented 2 years ago

What is the solution here? I want to remove the $type and the $id from some of my controllers that are exposed to third parties and do not want the additional payload of the breeze meta data.

marcelgood commented 2 years ago

@enkodellc These come from Newtonsoft not Breeze. Typically when using Breeze one replaces the default .NET Core Json Serializer with Newtonsoft, because it's richer for the types of object graphs Breeze endpoints return, and Breeze provides a default configuration that works out of the box, but you can add to it.

The default serializer doesn't handle circularity for example, but you can always use the .NET Core Json serializer for specific controllers and actions. Below is a link to a blog post showing some ways of how you can control the serialization at the action level. Basically you do the serialization yourself in the Action. Either using Newtonsoft with a different configuration from your global config, or using the .NET Core Json serializer in those actions.

https://makolyte.com/aspdotnet-how-to-make-the-controllers-use-newtonsoft/

BTW, for security reasons, you should probably create an entire separate service layer for your public API that you can deploy in a DMZ anyway, and that layer can use its own serialization, different from your internal Breeze service layer.

enkodellc commented 3 months ago

FYI, I needed this again so I built an attribute extension to handle it.

    [ExternalApiJsonReponse] //removes $type and $id from json
    [HttpGet]
    public async Task<Data> GetData()
    {
       return data;
     }
    public class ExternalApiJsonReponseAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        if (context.Result is ObjectResult objectResult)
        {
            var jsonSerializerSettings = new JsonSerializerSettings
            {
                NullValueHandling = NullValueHandling.Include,
                PreserveReferencesHandling = PreserveReferencesHandling.None,
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                TypeNameHandling = TypeNameHandling.None,
                Formatting = Formatting.Indented,
                ContractResolver = new DefaultContractResolver()
            };

            var json = JsonConvert.SerializeObject(objectResult.Value, jsonSerializerSettings);
            context.Result = new ContentResult
            {
                Content = json,
                ContentType = "application/json",
                StatusCode = objectResult.StatusCode
            };
        }

        base.OnActionExecuted(context);
    }
}