2 Stimmen

ASP.NET MVC2-Anwendung ruft WCF-Duplex-Dienst auf

Ich habe eine MVC2-Anwendung. Im Grunde möchte ich, dass ein Benutzer in meiner Rechnungsansicht auf "Rechnung anfordern" klickt und den WCF-Dienst aufruft. Der Dienst gibt dann einen Rückruf mit dem geschuldeten Betrag zurück. Ich bin mit 2 Probleme.

  1. Der Callback der Duplexmethode vom Client wird nicht ausgeführt oder nicht aufgerufen. Dies geschieht unregelmäßig. Manchmal wird sie aufgerufen und manchmal nicht
  2. Das zweite Problem ist, dass unabhängig davon, ob die Callback-Methode ausgeführt wird oder nicht, die Seite oder Anwendung kurz (innerhalb von 2-3 Sekunden) nach der Rückkehr der Ansicht geschlossen wird.

Meiner Ansicht nach gibt es Folgendes:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Bill
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Bill Summary:</h2>

    <td>
     <%: ViewData["ProcessingMessage"] %>
    </td>
    <table>
        <tr>
            <th>

                Username: 
            </th>
            <th>
                Total Number of Calls: 
            </th>
            <th>
                Amount to be Paid: 
            </th>
            <th>&nbsp;</th>
        </tr>
     <td>
    <%: ViewData["Username"] %>
    </td>
    <td>
    <%: ViewData["CallsCount"] %>
    </td>
     <td>
    <%: ViewData["TotalAmount"] %>
    </td>
    </table>
</asp:Content>

In meinem Controller habe ich die folgende Methode:

public class TelephoneController : Controller
    {
BillingCallback proxy = new BillingCallback();
 public ActionResult Bill()
        {
            ViewData["ProcessingMessage"] = "Processing Request.....";
            proxy.CallService(User.Identity.Name);
            return View();
        }
}

Ich habe eine Klasse für Callback erstellt:

public class BillController : Controller
    {
        private const double amountPerCall = 0.25;
        public double calcBill()
        {
            double total = amountPerCall;
            Log p = new Log();
            return total;
        }
        public ActionResult Index()
        {
            return View();
        }
    }

Nun zum Service:

[ServiceContract(CallbackContract = typeof(IBillCallBack))]
    public interface IBill
    {
        [OperationContract(IsOneWay = true)]
        void GetBilling(string username);
    }
    public interface IBillCallBack
    {
        [OperationContract(IsOneWay = true)]
        void CalculateBilling(string message);
    }

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)]
    class Bill : IBill
    {
        public void GetBilling(string username)
        {
            IBillCallBack callback = OperationContext.Current.GetCallbackChannel<IBillCallBack>();
            ThreadPool.QueueUserWorkItem(new WaitCallback(SendOperationToClient), callback);
        }
        public void SendOperationToClient(object stateinfo)
        {
            IBillCallBack callback;
            callback = stateinfo as IBillCallBack;
            string s = Thread.CurrentThread.ManagedThreadId.ToString();
            callback.CalculateBilling("username");
        }
    }

Irgendwelche Ideen?

2voto

Ladislav Mrnka Punkte 355028

Dies ist eine Wettlaufbedingung und eine falsche Verwendung des Duplex-Dienstes.

Was in Ihrem Code passiert:

  • Sie haben einen Controller, der einen Dienstvorgang aufruft
  • Der Dienstvorgang startet einen neuen Thread und gibt
  • Ihr Controller fährt mit der Verarbeitung fort und liefert ViewResult
  • In der Zwischenzeit verarbeitet der Arbeitsthread des Dienstes den Code und startet den Callback
  • Wenn der Worker nun schnell genug ist, wird Ihr Callback aufgerufen
  • Wenn der Worker nicht schnell genug ist, wird Ihre Ansicht bereits gerendert und Änderungen aus der Berechnung gehen verloren.
  • Wenn der Worker sehr langsam ist, wird der Controller aus dem Speicher freigegeben und auch der Proxy => Callback kann nicht aufgerufen werden, was wahrscheinlich zu einer Exception beim Service führt

Verwenden Sie einfach keinen Duplexdienst in einer Webanwendung. Es macht keinen Sinn, weil Sie immer noch auf den Rückruf warten müssen. Ich sehe keinen Unterschied zwischen dem Aufruf Ihres Dienstes mit Anfrage/Antwort-Muster und dem Aufruf der Berechnung als allgemeine Methode.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X