Alex Vergara
Alex Vergara

Reputation: 2219

Serialization based on model attributes

I am making a .NET 6 project, and I need to accomplish a task against an external API.

Let's define a model to set up the context.

class MyModel
{
    public bool field1;
    public string field2;
}

So, that model will be used in two actions. First, a GET request, that can NOT contain some of the fields above, and a POST request, that also can NOT contain some of the fields above.

For example:

// GET
{
    MyModel: {
        field1: true
    }
}

// POST
{
    MyModel: {
        field1: false,
        field2: "some value"
    }
}

So, when I perform a GET operation, I want to include some particular fields. And send it two another external API, so I read from API1, and send it to API2.

When I perform a POST operation, I read from API2, and insert data into API1, but I just want to include some predefined fields.

My desire it's to create a custom attribute to reflect that behaviour:

class MyModel
{
    [Read, Write]
    public bool field1;
    [Write]
    public string field2;
}

Also note that a field can be used also for the GET operation, althought for the POST operation.

I am getting lost in how to implement the behaviour of the Newtonsoft.Json package to make it understand how to deserialize and serialize those specific fields based on an input operation.

My first approach it's to define a Read and Write interfaces, and when a request for write is made to the external service, it will serialize the fields that has a Read annotation to send the data, and when a request is made for read, the model will know how to deserialize the content into the attributes that has a Write.

As you may notice, concepts are inverted. Read means send data to the external API (because it will be read from another but internal API of the project), and Write means read data from the external API (because will be inserted in our internal API).

Thanks.

Upvotes: 1

Views: 134

Answers (1)

Daniel
Daniel

Reputation: 9829

I would suggest to simply go for two models.

A Read Model

class MyReadModel
{
    public bool field1;
}

And a Write Model

class MyWriteModel
{
    public bool field1;
    public string field2;
}

This makes it very clear.

Think of other situations: E.g. you want to generate a API Documentation with Swagger. You would also have to deal with your custom attributes.

In you controller you will have to methods:

[YourAllowAttribute]
[HttpGet]
public async Task<ActionResult<MyReadModel>> Get()
{
    // stuff
}

[YourPostAttribute]
[HttpPost]
public async Task<ActionResult<MyReadModel>> Write()
{
    // stuff
}

Security trimming can be achieved by implementing two attributes or policies e.g. [YourAllowAttribute] or [YourPostAttribute].

With this approach you will not mix concerns in your model.

Upvotes: 4

Related Questions