0
votes

Attendre une demande au contrôleur d'un autre contrôleur - ASP .NET CORE

J'ai une application localApp code> avec un contrôleur API-contrôleur myController_a code>.

Lorsque quelqu'un envoie une demande à MyController_a code>, le contrôleur redirige La demande à une application différente RemoteApp code> et pause. p>

lorsque le remoteApp code> a effectué avec des calculs, il envoie une demande postale au localApp code>, à un autre contrôleur mycontroller_b code>. p>

La tâche consiste à attendre une requête postale à l'intérieur mycontroller_a code> à partir du mycontroller_b Code> Avant d'envoyer une réponse. P>

L'exemple ci-dessous pourrait aider à clarifier le problème: P>

public class MyController_A : ControllerBase
{
    public object Post([FromBody] MyModel message)
    {
        SendDataToAnotherApp(message);

        object result = new Task<object>(() => 
        {
            // Listening requests to MyController_B

            return request;

        }).Result;

        return result;
    }
}


5 commentaires

@mortb, merci pour la recommandation. Je ferai refacteur dès que je trouve un moyen de le faire fonctionner avec l'application distante :)


La demande de votre application distante n'a rien à voir avec la demande initiale à votre application. Donc, il vous suffit de vous assurer que l'application distante ne répond que lorsque la demande de B est également effectuée.


Ah maintenant je vois, l'application distante rappelle à Controller_B


@mortb, exactement. J'ai donc trouvé un moyen, comme je l'ai posté ci-dessous. Peut-être pas le meilleur, mais ça marche.


Le rappel comprend-il une pièce d'identité? Sinon, plusieurs rappels simultanés peuvent déclencher la mauvaise réponse


3 Réponses :


0
votes

Vous pouvez utiliser async / attendre pour votre contrôleur A

public class MyController_A : ControllerBase
{
    public async Task<object> Post([FromBody] MyModel message)
    {
        return await SendDataToAnotherApp(message);
    }
}


4 commentaires

Non, cela ne répond pas à ma question.


OP est de demander comment il peut attendre (A / Index) si la réponse se présente à différentes actions de contrôleur (B / Index).


Si vous dites de contrôler.index (), vous appelez contrôleur.index (). C'est juste faux et ne fais pas ça. Au lieu de cela, créez un service (Commonervice.cs) et injectez-le dans les deux contrôleurs.


@ Alex-TNILE, merci de réponse. Je le ferai plus tard, dès que je découvrirai, comment attraper l'autre demande



2
votes

Peut-être que vous devriez vous redéfinir l'architecture et ne pas garder votre contrôleur actif en attente de l'autre appel de retour.

Gardez à l'esprit que les demandes HTTP ont une durée limitée et une fois qu'ils ferment, les fils à l'intérieur mourront.

Je ne sais pas si c'est idéal pour votre occasion, mais je recommanderais d'utiliser SignalR pour envoyer les données à votre client via des sockets Web lorsque le deuxième contrôleur a terminé le travail.

aspnet / Signalr


3 commentaires

Merci de répondre. Le problème n'est que le RemoteApp. Son architecture restreint fortement mes possibilités :)


Mais je vais essayer de le redéfinir avec Signalr!


:) Je suis sûr que vous serez très satisfait: D



0
votes

donc, peut-être pas la meilleure solution, mais cela fonctionne.

J'ai sauvegardé la demande au mycontroller_b code> à l'intérieur du httpcontext.session et obtenez sa valeur à partir de MyController_a Code> . P>

public class MyController_B : ControllerBase {
    public void Post([FromBody] string message)
    {
        HttpContext.Session.SetString("MyController_B_request", message);
    }
}

public class MyController_A : ControllerBase
{
    public object Post([FromBody] MyModel message)
    {
        SendDataToAnotherApp(message);

        object result = new Task<object>(() => 
        {
            string request;
            while (true)
            {
                request = HttpContext.Session.GetString("MyController_B_request");
                if (!string.IsNullOrEmpty(request))
                    break;

                Task.Delay(1000).Wait();
            }

            return request;

        }).Result;

        return result;
    }
}


9 commentaires

Quel est le point de se débarrasser d'une tâche et d'y attendre de manière bloquante? En outre, c'est une jolie ... mauvaise façon faire des choses. Si l'utilisateur exécute deux demandes, vous n'avez aucune idée de laquelle on sera à l'intérieur de la session


Ou si c'est une application Web (même si ce n'est pas que dans votre contrôle, vous pouvez utiliser le client C # SingAlr C # sur l'application faisant le premier appel), terminez la première demande après appelant externe et utilisez Signalr pour notifier au navigateur que l'opération a été terminée. Donc, votre application Web peut initier une 2ème demande pour obtenir le résultat plutôt que de bloquer la connexion tout le temps.


@Tseng, merci pour votre commentaire! La tâche de blocage n'est pas pour une utilisation réelle. C'était en fait une méthode distincte, mais pour rendre le post plus compact, je l'emballe dans une tâche.


Je n'ai pas utilisé Signalr auparavant, mais sonne comme une bonne chose. Je vais l'essayer!


Démarrer une tâche et l'attendre (de manière bloquante) n'a toujours aucun sens. Qu'attendez-vous que cela fasse? Vous bloquez efficacement Deux threads , au lieu d'un si vous auriez simplement la boucle tandis que la méthode d'action (aucune tâche ou fil du tout). Et comme je l'ai dit, sur la concurrence (plusieurs demandes du même utilisateur) son dangereux


@Tseng, maintenant je comprends ce que tu veux dire :( Je dois apprendre toutes ces choses. Merci d'avoir clarifié.


Également sur le dessus si cela, votre code peut incroyablement travailler, avez-vous même testé dans un scénario réaliste? Lorsque myController_B est appelé, son appelé par le serveur distant, il n'y a donc pas de cookie de session. Les sessions sont spécifiques à l'utilisateur et le code distant écrirait à une session "Sans nom" et qu'elle n'apparaîtrait jamais dans la session d'utilisateurs en premier lieu et votre code à partir de myController_a ne terminerait jamais


Eh bien, pas spécifique de l'utilisateur mais demande spécifique et identifié par une clé unique fournie dans le cookie de session à être plus spécifique. Point est que le serveur rappel de l'arrière n'a pas ce cookie de session, non plus vous devriez le partager (problème de sécurité) - même si le serveur pouvait faire l'appel avec un cookie spécifique


@Tseng, Ah OK, dans ce cas, cela ne fonctionnerait que si je vais utiliser certaines ressources partagées, pas la session. Mais c'était condamné depuis le début :)