I subscribe to a mass email service which, when an error occurs at their end, posts to a page on my website as an endpoint to notify me that an email has bounced.
They describe it as follows:
The event data is sent in the POST request body using a JSON object.
What I need to know is how can I capture the info posted to me?
Currently I'm pointing them to a generic handler, a .ashx page, this can be changed to whatever as long as it's in .NET.
In 10 years working with first classic ASP and now .NET I've never done this before and I must admit I don't even know where to start.
This is the code I used to achieve a similar thing - not sure where I got it originally.
C#
var strJSON = String.Empty;
context.Request.InputStream.Position = 0;
using (var inputStream = new StreamReader(context.Request.InputStream))
{
strJSON = inputStream.ReadToEnd();
}
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
object serJsonDetails = javaScriptSerializer.Deserialize(strJSON, typeof(object));
// go and process the serJsonDetails object
or VB
Dim strJSON = [String].Empty
context.Request.InputStream.Position = 0
Using inputStream = New StreamReader(context.Request.InputStream)
strJSON = inputStream.ReadToEnd()
End Using
Dim javaScriptSerializer As New JavaScriptSerializer()
Dim serJsonDetails As Object = javaScriptSerializer.Deserialize(strJSON, GetType(Object))
' go and process the serJsonDetails object
You could just read the Request stream (Request.GetRequestStream) and use Json.NET to deserialize to an object.
You could use MVC4 and the built in object mapping.
There's many options. Perhaps you should read up on them more so that you have an idea of their capabilities and drawbacks.
Probably Request.Form (here) will help you get the JSON, if you know the content of the post, and then you need something like json.net library to get the object, or you can simply search the string using regex or keywords
Or if you can direct the post to a web service(asmx) instead of a web page, those services will parse the json for you
If you need to read raw post data twice or many times, i advice you to use this code.
string postBodyJson = null;
MemoryStream ms = new MemoryStream();
Request.InputStream.Position = 0;
Request.InputStream.Seek(0, SeekOrigin.Begin);
Request.InputStream.CopyTo(ms);
ms.Position = 0;
ms.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(ms))
{
postBodyJson = reader.ReadToEnd();
}
Related
I have developed a client page for wcf service. basically my page has one button and two textboxes one is for loading request xml from xml file, and another one is displaying response xml.
Problem is that after any error got from wcf service my request xml textbox ignores all xml nodes it just displays node values with even spaces.
this is working in one machine it is not working in another machine.
two machines are windows xp os, ie 7.
<TextBox ID="requesttextbox" runat="server" TextMode="MultiLine" Width="470px"
Height="300px" Wrap="false/>
button click code something like this
System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
xmlDoc.XmlResolver = null;
xmlDoc.LoadXml(requesttextbox.Text);
HttpWebRequest objHttpWebRequest = null;
HttpWebResponse objHttpWebResponse = null;
string strFinalRequestXML = xmlDoc.OuterXml;
objHttpWebRequest = (HttpWebRequest)WebRequest.Create("RequestURL");
objHttpWebRequest.Method = "POST";
objHttpWebRequest.Accept = "xml";
objHttpWebRequest.ContentType = "application/xml; charset=utf-8";
objHttpWebRequest.Timeout = 300000;
objHttpWebRequest.ContentLength = strFinalRequestXML.Length;
System.IO.StreamWriter sw = new System.IO.StreamWriter (objHttpWebRequest.GetRequestStream());
sw.Write(strFinalRequestXML);
sw.Close();
try
{
objHttpWebResponse = (HttpWebResponse)objHttpWebRequest.GetResponse();
Stream streamResponseText = objHttpWebResponse.GetResponseStream();
StreamReader srFinalResponseText = new StreamReader(streamResponseText, Encoding.UTF8);
txtResponse.Text = string.Empty;
// formattin xml string to as xml nodes to display in textbox
System.Xml.Linq.XElement element = System.Xml.Linq.XElement.Parse(srFinalResponseText.ReadToEnd());
txtResponse.Text = element.ToString();
strStatusCode = objHttpWebResponse.StatusCode.GetHashCode().ToString();
}
catch (WebException objWebException)
{
}
For example:
request xml <node>test</node> <node1>test;</node1> inside request xml text box.
after error from wcf display as " test test".
i have no clue for this problem.
If you are truly using WCF, you shouldn't have to manually call the URL using HttpWebRequest and HttpWebResponse, nor should you have to parse the XML by hand. You should add the service to the Service References, see:
http://msdn.microsoft.com/en-us/library/bb628652.aspx
If it is not WCF, but instead a regular SOAP web service, you can still add it as a Web Reference, see:
http://msdn.microsoft.com/en-us/library/bb628649.aspx
Then you can write code that is a little easier:
using (var client = new MyService.MyServiceClient())
{
string foo;
foo = client.MyMethod();
}
As for the text display, there is nothing in your catch handler, so I'm not sure where the textbox would be getting any sort of value. You must be setting it somewhere outside the code snippet you have provided.
Set xml = Server.CreateObject("Microsoft.XMLHTTP")
xml.Open "GET", "http://www.indexguy.com/request_server.cfm?member_id=15893&id="+request.querystring("id")+"&"+request.querystring, False
xml.Send
How can I build the querystring parameter to a string object in C#/VB.NET
"member_id=15893&id="+request.querystring("id")+"&"+request.querystring"
If you are looking to build a querystring, String.Format("{0}", arg) might be a cleaner method to construct it.
For ASP.NET, you're going to want to replace the Server.CreateObject("Microsoft.XMLHTTP") with HttpWebRequest.
As for building the query string, that's still identical. You can still retrieve query string parameters by indexing into Request.QueryString. If you're using C# you can keep the + for string concatenation but might be more acceptable to use & in VB.
In ASP.NET the Page class exposes a Request property which provides access to a QueryString property - this is a NameValueCollection that lets you get values out in much the same way as in your existing example, by specifying keys:
var id = Page.Request.QueryString("id");
var newQuery = string.Format("?member_id=15893&id={0}&", id);
The above can easily be expanded to build more into your required query string.
As for the request you're initiating, that can be achieved using a WebRequest instance; to alter the sample from MSDN only slightly, here is an example:
WebRequest request = WebRequest.Create(yourUrl + newQuery);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Response.Write(response.StatusDescription);
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader (dataStream);
string responseFromServer = reader.ReadToEnd();
Response.Write(responseFromServer);
reader.Close();
dataStream.Close();
response.Close();
I am using the following code to export a data set to an Excel sheet.
[WebMethod]
public static void ExporttoExcel()
{
DataSet ds;
productfactory pf=new productfactory();
ds = pf.getproducts();
HttpResponse response = HttpContext.Current.Response;
// first let's clean up the response.object
response.Clear();
response.Charset = "";
response.ContentEncoding = System.Text.Encoding.Default;
// set the response mime type for excel
response.ContentType = "application/vnd.ms-excel";
response.AddHeader("Content-Disposition", "attachment;filename=\"products.xls\"");
// create a string writer
using (StringWriter sw = new StringWriter())
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
// instantiate a datagrid
DataGrid dg = new DataGrid();
dg.DataSource = ds.Tables[0];
dg.DataBind();
dg.RenderControl(htw);
string filepath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\products.xls";
response.Write(sw.ToString());
// response.End();
}
}
}
The problem is that it's not raising file download and hence no export is taking place. The same code works fine in a normal method. But with the web method it's not working.
I suggest to make an HttpHandler ending in ashx, and place inside him your code that create the excel file.
then call it from your javascript code like that.
document.location.href = "ExporttoExcel.ashx";
The problem is that WebMethods are not designed to allow you to interact with the Response object (evident in that it wasn't available and you had to use HttpContext.Current.Response to get to it). WebMethods are designed to be blackbox to the user. They will perform and action and/or return a value.
Perhaps you can give us a better idea of what you are trying to accomplish and we can suggest an alternate solution.
u can use to create a dynamic iframe with URL set to the Web Handler to generate the Excel this will raise the file download with out posting the current page.
I'm about to launch a site that was working well until I found the following hiccup:
I can't request a Yahoo! Pipe over SSL.
So the pages that require SSL are now missing a piece of their functionality unless I figure out a way around this; obviously, this could be done if I use an SSL-hosted page on my app to request the Yahoo! pipe for me.
I've seen solutions like http://www.iisproxy.net/license.html, but it seems to be a bit heavy for what I'm trying to do.
Can't I do this with a simple ASHX handler? Or is it more complex than that?
Thank you,
Michael
Thank you, John -- in case it's helpful to anyone else, here's the code I'm using in my ASHX file:
public override void ProcessRequest(HttpContext context)
{
var strURL = context.Server.UrlDecode(context.Request["url"]);
WebResponse objResponse = default(WebResponse);
WebRequest objRequest = default(WebRequest);
string result = null;
objRequest = HttpWebRequest.Create(strURL);
objResponse = objRequest.GetResponse();
StreamReader sr = new StreamReader(objResponse.GetResponseStream());
result = sr.ReadToEnd();
//clean up StreamReader
sr.Close();
//WRITE OUTPUT
context.Response.ContentType = "application/json";
context.Response.Write(result);
context.Response.Flush();
}
However, I was getting a couple extra characters (as opposed to the version that came direct from Yahoo! Pipes), so I had to remove those before parsing the JSON.
I guess if all you want to do is read the contents of a request you could use a WebRequest & WebResponse
here are some details on using that
http://www.west-wind.com/presentations/dotnetWebRequest/dotnetWebRequest.htm
I want to send emails in HTML format. How can I use asp.net to generate HTML content for emails.
Using output of .aspx page(Tried there was nothing in email body. Must be something in page that can't be used for email)
Using Webcontrol and get web control output and use it as email body.
Using custom http handler so can call handler to get email body.
Can you please suggest what would be the best solution?
Some guide or sample reference would be great if know one.
Thanks for all answers:
I am implementing code below:
string lcUrl = "http://localhost:50771/webform1.aspx";
// *** Establish the request
HttpWebRequest loHttp =
(HttpWebRequest)WebRequest.Create(lcUrl);
// *** Set properties
//loHttp.Timeout = 10000; // 10 secs
loHttp.UserAgent = "Code Web Client";
// *** Retrieve request info headers
HttpWebResponse loWebResponse = (HttpWebResponse)loHttp.GetResponse();
Encoding enc;
try
{
enc = Encoding.GetEncoding(loWebResponse.ContentEncoding);
}
catch
{
enc = Encoding.GetEncoding(1252);
}
StreamReader loResponseStream =
new StreamReader(loWebResponse.GetResponseStream(), enc);
string lcHtml = loResponseStream.ReadToEnd();
loWebResponse.Close();
loResponseStream.Close();
I think the ASPX file will make the most easy to edit mechanism. You can use
var stream = new MemoryStream();
var textWriter = new StreamWriter(stream);
Server.Execute("EmailGenerator.aspx", textWriter);
to capture the output of that page.
I personally don't like any of your options. I would probably do it by using an HTML file (or a template stored in a database) and substituting something like {{name}} with the appropriate parameter.
I did this, essentially we had a page that the user could view, and then they could click a button and send the html on the page in an email. Basically my page was responsible for generating the email. I did this by overriding the Render method, and providing my own stream or using the one passed to us. We did this dpeneding on if we were rendering what the user would see or emailing it.
protected override void Render(HtmlTextWriter writer)
{
if (_altPrintMethod)
{
System.Net.Mail.MailMessage....
mailMsg.Body=RenderHtml(baseUrl);
}
}
protected virtual string RenderHtml(string baseUrl)
{
RemapImageUrl(baseUrl);
StreamWriter sw = new StreamWriter(new MemoryStream());
HtmlTextWriter writer = new HtmlTextWriter(sw);
base.Render(writer);
writer.Flush();
StreamReader sr = new StreamReader(sw.BaseStream);
sr.BaseStream.Position = 0;
return sr.ReadToEnd();
}
One thing to note is you have to make sure all links are fully qualified. You might be able to use the base functionality. this is what I was doing in the RemapImageUrl basically I appended an absolute path on all my image files.