ASP.NET MVC2 application calling WCF duplex service
I have an MVC2 application. Basically, in my Bill view, I want a user to click "Request Bill" and it calls the WCF service. The service then returns back a callback with the amount owed. I am having 2 issues.
- The duplex method callback from the client does not execute or does not get called. This happens intermithtently. Sometimes it gets called and sometimes it does not
- The second problem is that whether the callback method executes or not, the page or application closes shortly (within 2-3 seconds) after returning the view.
In my view, I have the following:
<%@ 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>
开发者_StackOverflow社区 Total Number of Calls:
</th>
<th>
Amount to be Paid:
</th>
<th> </th>
</tr>
<td>
<%: ViewData["Username"] %>
</td>
<td>
<%: ViewData["CallsCount"] %>
</td>
<td>
<%: ViewData["TotalAmount"] %>
</td>
</table>
</asp:Content>
In my controller, I have the following method:
public class TelephoneController : Controller
{
BillingCallback proxy = new BillingCallback();
public ActionResult Bill()
{
ViewData["ProcessingMessage"] = "Processing Request.....";
proxy.CallService(User.Identity.Name);
return View();
}
}
I created a class for callback:
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();
}
}
Now for the 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");
}
}
Any ideas?
That is race condition and wrong usage of duplex service.
What happens in your code:
- You have a controller which calls service operation
- The service operation starts new thread and returns
- Your controller continues with processing and returns ViewResult
- In the mean time worker thread on service process code and starts callback
- Now if the worker is fast enough your callback is called
- If the worker is not fast enough your View is already rendered and changes from calculation are lost
- Moreover if worker is really slow controller is released from memory and proxy as well => callback cannot be called which probably results in exception on service
Simply don't use duplex service in web application. It doesn't make sense because you still have to wait on callback - I don't see any differnce in calling your service with request/response pattern and than calling calculation as common method.
精彩评论