How to create a Restful API with asynchronous processing and response using C# + Angular(v5+)

Asked

Viewed 782 times

6

Hello, I am working with C# and I have the following problem:

Imagine I have a route to my API api/estoque/inventario where this route should make the calculation of the inventory of the entire application stock and on demand return the result. To set up this API route, I would have something similar to this:

namespace Api
{
  public class Estoque { ... }

  [Route("api/estoque/inventario")]
  [ApiController]
  public class EstoqueController: ControllerBase
  {
    [HttpGet]
    public async Task<IActionResult<ICollection<Estoque>>> GetInventario()
    {
      try
      {
        // pega os produtos
        // faz todas as regras de negócio (síncronas e assíncronas)
        // retorna o estoque com o inventário (como?)
      }
      catch(Exception ex)
      {
        throw;
      }
    }
  }

}

The problem is that even if I have an asynchronous task in my API, the answer to my client is not asynchronous. On the Client side, I use the library Rxjs together with the Angular and the service that makes the requests to the API has the return of an observable object, thus:

export const API_URL = '...';

export interface IEstoque { ... }

@Injectable({
  providedIn: 'root',
})
export class EstoqueService {

  private baseUrl: string = "/api/estoque";

  constructor(public http: HttpClient) { }

  public getInventario(): Observable<IEstoque[]> {
    return this.http.get(`${API_URL}${this.baseUrl}/inventario`);
  }

}

My intention is to use the list of processed items in stock along with the pipe Asyncpipe which exists at the angle, which makes it possible for me to make an asynchronous loop based on the return of service, thus:

<div *ngFor='let estoque of estoqueList | async'>
  {{estoque | json}}
</div>
@Component({
  selector: 'estoque-list',
  templateUrl: 'estoque-list.component.html',
})
export class EstoqueList {

  public estoqueList: Observable<IEstoque[]>;

  constructor(public estoqueService: EstoqueService) {
    this.estoqueList = estoqueService.getInventario();
  }

}

What I need to do to get my route api/estoque/inventario will send the inventory list asynchronously and continuously to my processing-based frontend?

  • 2

    In this case to send continuous data better use websockets. I do not know how do in c#.

  • 2

    One thing I don’t understand, when you say the server side needs to be asynchronous, for what reason? You described that you want to "do the inventory calculation of the entire application stock and by demand return the result", what would that be on demand? You want an application that listens and as new data appear in stock it is already showing in this application in "real time"?

  • 2

    The statement of his api is correct, now you need to see what’s left of the code within it. All chain calls, in all layers/projects you have a call from your api must return tasks async, and be called using await, or will not function properly asynchronously

  • What I need to do is what Eduardo said, like websockets, only I have no idea how to do it in C#

  • This would be an update in Altime Juliano. The apication itself is a logistics control application and this needs to be managed in Altime.

  • Yes Ricardo, I am aware of this, so much so that I am generating an Api and not a layer of direct access to data.

  • 1

    Wow, I don’t understand your doubt, the flames in the service and the method in the C are no longer asynchronous#?

  • Even if the calls are asynchronous in the service, the return of the content is not asynchronous, I have to process all the data before returning. The intention is that I may return gradually, I believe that as Eduardo said with websockets

  • 1

    If you know some nodejs recommend https://socket.io/

  • i have custom of working with socket.io in Nodejs, the problem is that the person of the company where I work does not want to change technology, therefore I am obliged to use C# + Aspnetcore + Angular...

  • 1

    As much as you make a partial flush and watching the response stream, still what you would receive would be an incomplete, invalid Json. If you want a real-time broadcast you will need to completely change your architecture.

  • I was even seeing here about Laravel’s Broadcast, what he and Socket.io do is what I’m looking for

  • If you want to work via websockets, you can use signalr on . net and make the communication. Asp.net/signalr. At the angle already have signaling libraries too.

  • @When I say I need to send it asynchronously, it’s because I can’t do everything and then send... My idea is to send whenever you have completed a stock item so that it does not lock the application on both sides

  • @Ricardopunctual I do this does not guarantee that the shipment to the customer will be asynchronous, ie by finalizing calculation

Show 10 more comments

2 answers

2

Leandro, your API signature is asynchronous. This means that in this part (method signature) it is correct. But let’s go over a few things here that might be interfering with what you want.

1 - The whole flow shall be asynchronous.

When working synchronously, everything must be synchronous. Likewise, when working asynchronously, everything must be asynchronous. This is because mixing the behaviors brings unwanted results. So make sure that all the code, data stream and all the processing is also asynchronous, not just the signature of your method. PS: Play everything inside Task.Factory.StartNew is not a way...

2 - The keyword async in your API does not make HTTP asynchronous.

Remember that HTTP itself is not asynchronous. That is, your client (Javascript) will always wait for the server response and even if your method in the API is asynchronous, your interface will not necessarily be. Using async in method signature is related to the internal request/response, call receiving thread allocation and I/O, and does not allow your interface to be more responsive. Basically, using async makes your API lighter and more scalable, especially when it needs to "follow" for slower tasks (like fetching data in a database).

This means that the client (Javascript) will, yes, wait for all the processing to take place and finally receive the answer. The difference is that while the client waits, the I/O thread that would be stuck waiting for the answer (and this thread belongs to a finite number group) will not get stuck and can be used for other requests (faster, for example). But the client will remain waiting until all processing is complete and the result is returned by your API.

3 - So how to improve the experience?

There are several methods and there is no definite answer because each scenario has a different output. In some cases, a "loading" screen (indicating loading) is enough. In others it may be necessary to use Signalr or Socketio to send data as it becomes available. In other scenarios you can create a processing task and return a kind of ID that you can consult later (from time to time) to know if it has already been completed. It all depends on what exactly you want, the requirements of the project (and the client) and the expected total processing time. Just as it is intolerable to leave a "loading..." locked for 4h to process the data, it is unrealistic to create an entire Signalr structure for a task that takes 1 second to be processed.

  • i am used to using this with socket.io in Laravel and also Nodejs but I did not find any code "readable" and simple to understand to implement this feature in an acceptable and scalable way...

  • @Leandroluk As the client depends on an open connection with the server so that real-time communication happens, two, one: either you will create an API-Gateway or Proxy or similar that will be responsible for receiving the connections and making internal calls, or your gateway/proxy/etc should understand and promote a fixation so that calls are always redirected to the same server on a farm.

  • I thought I would provide this using Websocket’s, where I would implement the same next to the HTTP HEAD method, where it would by itself serve to tell me the status of the content... the idea is to do something like firebase does...

  • On the client’s side, you’re right. On the server side, Firebase is using a gateway that redistributes tasks across multiple replicated server nodes. If you’re going to make the server "scalable" too, you have to think of the application’s client side as well :)

-1

When we use Api, we make requests, when the method is async it will not send you anything asynchronous as user responses, and as we work with API request, we will not have anything constant, for this you should research on Socketi that will make this better your need, today in 2019 one of the novelties of Microsoft is the Razorcomponent, that will make a WEB application using Signalr and tals so you will be really connected to your Backend being able to do this asynchronous method that needs to.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.