Hi --
I'm trying to submit some Json data to an ASP.NET MVC controller from a WPF app. I wrote my client-side code based on a couple of samples from MSDN using the WebRequest object and BeginGetResponse. This worked fine when I was just sending a GET request. It hit my ASP.NET MVC controller just fine and brought back some Json data. But when I try to switch to using a POST verb, it isn't working. I know the controller is wired up okay, because I can hit it from a web browser typing in the URL manually. I'm pretty sure I must be making a mistake in how I set up the POST.
I'm including the code below up to the point where I issue the BeginGetResponse. (I don't include my async BeginGetResponse callbacks, because the request times out and never hits the callback. If someone can tell me what I am doing wrong, I would be greatly appreciative.
On the client side here's the setup code (following it below I have my asp.net mvc controller code). I call the WebRequest_BeginGetResponse.GetResponse method in the following code from a WPF button click handler, passing in my target url, which I am 100% certain is the correct one:
public class RequestState
{
// This class stores the state of the request.
const int BUFFER_SIZE = 1024;
public StringBuilder requestData;
public byte[] bufferRead;
public WebRequest request;
public WebResponse response;
public Stream responseStream;
public RequestState()
{
bufferRead = new byte[BUFFER_SIZE];
requestData = new StringBuilder("");
request = null;
responseStream = null;
}
}
class WebRequest_BeginGetResponse
{
public static ManualResetEvent allDone = new ManualResetEvent(false);
const int BUFFER_SIZE = 1024;
Window1 ui;
delegate void PlainMethod();
StringBuilder theResults;
const int DefaultTimeout = 2 * 60 * 1000; // 2 minutes timeout
// Abort the request if the timer fires.
private static void TimeoutCallback(object state, bool timedOut)
{
if (timedOut)
{
HttpWebRequest request = state as HttpWebRequest;
if (request != null)
{
request.Abort();
}
}
}
public WebRequest_BeginGetResponse(Window1 userInterface)
{
ui = userInterface;
theResults = new StringBuilder();
}
public void GetResponse(string url)
{
// Create a new webrequest to the mentioned URL.
WebRequest myWebRequest = WebRequest.Create(url);
myWebRequest.Method = "POST";
myWebRequest.ContentType = "application/json";
Stream requestStream = myWebRequest.GetRequestStream();
DataContractJsonSerializer theSerializer = new DataContractJsonSerializer(typeof(List<string>));
List<string> theAddressList = new List<string>();
theAddressList.Add("[email protected]");
theAddressList.Add("[email protected]");
theAddressList.Add("[email protected]");
theAddressList.Add("[email protected]");
theAddressList.Add("[email protected]");
theSerializer.WriteObject(requestStream, theAddressList);
// myWebRequest.ContentLength = requestStream.Length;
// Create a new instance of the RequestState.
RequestState myRequestState = new RequestState();
// The 'WebRequest' object is associated to the 'RequestState' object.
myRequestState.request = myWebRequest;
// Start the Asynchronous call for response.
IAsyncResult asyncResult = (IAsyncResult)myWebRequest.BeginGetResponse(
new AsyncCallback(RespCallback), myRequestState);
ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), myWebRequest, DefaultTimeout, true);
// The response came in the allowed time. The work processing will happen in the
allDone.WaitOne();
myRequestState.response.Close();
ui.Dispatcher.Invoke(DispatcherPriority.Normal, (PlainMethod)delegate
{
ui.textBlock1.Text = theResults.ToString();
});
// Release the WebResponse resource.
}
Here's the ASP.NET MVC controller code:
public class NotifyEmailController : Controller
{
//
// GET: /NotifyEmail/
[JsonFilter(Param="theSendRequest",RootType=typeof(NotifyEmailAddressRequest))]
// [AcceptVerbs(HttpVerbs.Post)]
public NotifyEmailAddressActionResult ToAddress(NotifyEmailAddressRequest theSendRequest)
{
NotifyEmailAddressActionResult theResult = new NotifyEmailAddressActionResult();
EmailSender theMailer = new EmailSender();
theResult.Success = theMailer.SendMail();
return theResult;
}
[JsonFilter(Param = "theSendRequest", RootType = typeof(NotifyEmailAddressListRequest))]
// [AcceptVerbs(HttpVerbs.Post)]
public NotifyEmailAddressListActionResult ToAddressList(NotifyEmailAddressListRequest theSendRequest)
{
List<string> theSubmittedList = theSendRequest.EmailList;
return new NotifyEmailAddressListActionResult();
}
}
}
The JsonFilter is a small ActionFilter that deserializes the json data into an object. It (and the controller) both get invoked when I submit a url manually from a web browser, but not when I use the client code posted above. It's code is this:
public class JsonFilter : ActionFilterAttribute
{
public string Param { get; set; }
public Type RootType { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if ((filterContext.HttpContext.Request.ContentType ?? string.Empty).Contains("application/json"))
{
object o = new DataContractJsonSerializer(RootType).ReadObject(filterContext.HttpContext.Request.InputStream);
filterContext.ActionParameters[Param] = o;
}
}
}
Thanks for any help that anyone can provide.
Regards,
Mike