HTTP Post using .Net C# in speedway connect software - c#

I am using RFID Speedway connect software in the Speedway reader, I got a PHP sample for HTTP Post and after googled sometime I couldn't find the sample for .Net C#. So I tried in simple asp.net application[hosted in IIS] to receive the HTTP post response from the reader but I never get in to it.
Below is my sample code.
URL assigned in the reader is http://MY_IP/Default.aspx
My asp.net code sample is :
protected void Page_Load(object sender, EventArgs e)
{
System.Text.StringBuilder displayValues = new System.Text.StringBuilder();
System.Collections.Specialized.NameValueCollection postedValues = Request.Form;
Label1.Text = postedValues.AllKeys.Length.ToString();
}
my page never got hit. Can anyone tell me how to achieve the HTTP Post response in C#.
Thanks

Try using a generic handler
myHandler.ashx
public class myHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string requestStr= new StreamReader(context.Request.InputStream).ReadToEnd();
context.Response.ContentType = "application/text";
switch (context.Request.HttpMethod)
{
case "GET":
break;
case "POST":
context.Response.Write("ok");
break;
default:
break;
}
}
public bool IsReusable
{
get { return false; }
}
}

Related

Web API and HTTP Module

We have an HTTP Module that decodes all encoded requests.
It works great with all WCF requests, but NOT in Web Api requests- in Web Api the request (both POST and GET) gets to the service still encoded
I see that it Hits the HTTP Module but,again,still gets to the service encoded.
How can i fix it? or what am i doing wrong?
i know that its better to work with Message Handlers in Web Api, but HTTP Modules suppose to work too- no?
HTTP Module:
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
context.EndRequest += context_PreSendRequestContent;
}
void context_PreSendRequestContent(object sender, EventArgs e)
{
string encodedQuerystring = HttpContext.Current.Request.QueryString.ToString();
if (!string.IsNullOrEmpty(encodedQuerystring))
{
System.Collections.Specialized.NameValueCollection col = new System.Collections.Specialized.NameValueCollection();
col.Add("q", encodedQuerystring);
WebFunction.CreateQuerystring(HttpContext.Current, col);
}
}
void context_BeginRequest(object sender, EventArgs e)
{
string encodedQueryString = String.Empty;
if (HttpContext.Current.Request.QueryString.Count > 0 && HttpContext.Current.Request.QueryString["q"] != null)
{
object _p = HttpContext.Current.Request.QueryString;
encodedQueryString = HttpContext.Current.Server.UrlDecode(HttpContext.Current.Request.QueryString["q"].ToString());
string originalQueryString = HttpContext.Current.Server.UrlDecode(WebFunction.Base64Decode(encodedQueryString));
if (!string.IsNullOrEmpty(originalQueryString))
{
WebFunction.CreateQuerystring(HttpContext.Current, WebFunction.ConvertQueryToCollection(originalQueryString));
}
}
}
WebFunction:
public static void CreateQuerystring(HttpContext context, System.Collections.Specialized.NameValueCollection nameValueCollection)
{
// reflect to readonly property
PropertyInfo isreadonly = typeof(System.Collections.Specialized.NameValueCollection).GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
// make collection editable
isreadonly.SetValue(context.Request.QueryString, false, null);
context.Request.QueryString.Clear();
context.Request.QueryString.Add(nameValueCollection);
// make collection readonly again
isreadonly.SetValue(context.Request.QueryString, true, null);
}
Web Api:
public class NamesController : ApiController
{
[HttpGet]
[ActionName("GET_NAMES")]
public Drugs_ResponseData Get(string q)
{
//need to add the decode function to get it to work
string[] arrAmpersant = Commonnn.DecodeFrom64(q).Split('&');
Names_obj = new Names();
return _obj.GetResult(Convert.ToInt32(Commonnn.GetValFromEqual(arrAmpersant[0])));
}
}
It seems that the Web API doesn't use the QueryString collection in the request, but it parses the URL itself.
See the GetQueryNameValuePairs method in this file - they take the Uri and parse its Query property.
So you have two options to do that:
The dirty one is to change the Uri of the request in your the HTTP module. I don't know whether it's possible, but some reflection could do the trick.
The nicer way would be to use the Web API message handler.
May I suggest you use Context.Items and let the QueryString have the encoded version.
It's a not very well known built in key/value dictionary which last throughout a request where you easily store any object and then share it between module, handlers, etc.
Using this would very like give you a better performance than unlocking the QueryString object, but more importantly, you process the value in one place and reuse it in many, and when needed, you just add a second value, the complete QueryString collection or any other value you want to share across a request.
void context_BeginRequest(object sender, EventArgs e)
{
string encodedQueryString = String.Empty;
if (HttpContext.Current.Request.QueryString.Count > 0 && HttpContext.Current.Request.QueryString["q"] != null)
{
string encodedQueryString = HttpContext.Current.Server.UrlDecode(HttpContext.Current.Request.QueryString["q"].ToString());
HttpContext.Current.Items("qs_d") = HttpContext.Current.Server.UrlDecode(WebFunction.Base64Decode(encodedQueryString));
}
}
Web Api:
public class NamesController : ApiController
{
[HttpGet]
[ActionName("GET_NAMES")]
public Drugs_ResponseData Get(string q)
{
string[] arrAmpersant = Commonnn.DecodeFrom64(HttpContext.Current.Items("qs_d").ToString()).Split('&');
Names_obj = new Names();
return _obj.GetResult(Convert.ToInt32(Commonnn.GetValFromEqual(arrAmpersant[0])));
}
}
Side note: I see you call HttpContext.Current.Server.UrlDecode twice. I don't think you need that unless your Base64Decode method encode the value again.
You can handle like this
protected void Application_BeginRequest(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
string path = app.Context.Request.Url.PathAndQuery;
int pos = path.IndexOf("?");
if (pos > -1)
{
string[] array = path.Split('?');
app.Context.RewritePath(array[0]+"?"+ HttpContext.Current.Server.UrlDecode(array[1]));
}
}
Adding on to #Tomáš Herceg 's answer, I would implement a Web Api message handler rather than modifying your HttpModule to accommodate Web Api.
public class DecodeQueryStringMessageHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (request.Method == HttpMethod.Get)
{
var originalQueryString = request.RequestUri.Query;
if (!string.IsNullOrEmpty(originalQueryString))
{
var ub = new UriBuilder(request.RequestUri) { Query = HttpUtility.UrlDecode(originalQueryString) };
request.RequestUri = ub.Uri;
}
}
return base.SendAsync(request, cancellationToken);
}
}
It is possible, but you will need reflection, what means that exist a risk here. Please, let me suggest you what I consider to be a more clean solution after the solution.
Solution
if (!string.IsNullOrEmpty(originalQueryString))
{
var request = HttpContext.Current.Request;
request.GetType().InvokeMember("QueryStringText", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, request, new[] { "q=" + originalQueryString });
//WebFunction.CreateQuerystring(HttpContext.Current, WebFunction.ConvertQueryToCollection(originalQueryString));
}
This will update the following properties of the Request:
Request.Param
Request.QueryString
Request.ServerVariables
Request.Url
but will not update the:
Request.RawUrl
Cleaner Solution
IIS URL Rewrite Module
http://www.iis.net/learn/extensions/url-rewrite-module/developing-a-custom-rewrite-provider-for-url-rewrite-module

How can I get my Json object from URL, Windows Phone 8.1 (C#)

Suppose I have this data:
{
"A": "Z",
"B": {
"C": "Y",
"D": "X"
}
}
stored in this link.
now I want this data from my windows phone app during a button click.
private void login(object sender, RoutedEventArgs e)
{
//I want to read the json data here
}
Previously I have tried DownloadStringAsync method of WebClient. But this class is no longer available in System.Net. I would like to know the place and documents where I can learn how to get and post data using url.
Thanks.
using (var client = new WebClient())
{
var uri = "https://api.myjson.com/bins/2hxei";
var result = System.Text.Encoding.Default.GetString(client.DownloadData(uri));
// result : {"A":"Z","B":{"C":"Y","D":"X"}}
}
btw. WebClient is definitely still available in .NET
If you really do not want to use Web Client (older) and want to use the newer Http Client instead, use the following code.
public static string GetJsonData()
{
var promise = GetWebStringAsync("https://api.myjson.com/bins/2hxei");
// do something else if needed
var jsonData = promise.Result;
return jsonData; //{"A":"Z","B":{"C":"Y","D":"X"}}
}
public static async Task<string> GetWebStringAsync(string uri)
{
using (var client = new HttpClient())
{
var stringTask = await client.GetStringAsync(uri);
return stringTask;
}
}
Here, if you want, rather than doing var stringTask = await client.GetStringAsync(uri) you can also do var jsonString= client.GetStringAsync(uri).Result directly. But you'll lose the benefits of aynchronous method there, and the call will be synchronous. The calling thread will wait there until response is received from the web call.

Creating an embedded image button in ASP.net?

I need to create a button in ASP.net that I can embed into another web page.
Essentially the button will query a DB server side on page load and then change it's image depending on the return of the query.
Does anyone know the best approach for this? I am not a pro at ASP.net as you can tell. Written in C# preferably.
In this case I would suggest using a IHttpHandler instead of a generic WebForm. https://msdn.microsoft.com/en-us/library/system.web.ihttphandler(v=vs.110).aspx
The handler is more suitable for this request as it will be able to respond quickly and is purpose built for handling specific requests that are not necessarily HTML based. This can be quite simple to wire up to accept a request, query the database and generate an image that you choose. Now you haven't provided much information about where the image comes from but lets look at a simple request.
To begin in a webforms web application select a new GenericHandler which we will name DynamicImage.ashx. Which will build our initial template as below.
public class DynamicImage : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write("Hello World");
}
public bool IsReusable
{
get
{
return false;
}
}
}
This template provides the basics to handle our request. When the request arrives the WebServer will execute the ProcessRequest() method passing in the HttpContext as a parameter. From here we can use this to deliver our response.
For argument sakes lets say we are querying the image based on the QueryString parameter username which represents a user in our database. I have included some basic code on your steps to achieve this. (Code commented)
public void ProcessRequest(HttpContext context)
{
//get our username from the query string
var username = context.Request.QueryString["username"];
//clear the response and set the content type headers
context.Response.Clear();
context.Response.ContentType = "image/png";
//if the username is empty then end the response with a 401 not found status code
if (string.IsNullOrWhiteSpace(username))
{
context.Response.StatusCode = 401;
context.Response.End();
return;
}
//do a db query to validate the user. If not valid do a 401 not found
bool isValidUser = new UserManager().IsValidUser(username);
if (!isValidUser)
{
context.Response.StatusCode = 401;
context.Response.End();
return;
}
//get the user image file path from a server directory. If not found end with 401 not found
string filePath = context.Server.MapPath(string.Format("~/App_Data/userimages/{0}.png", username));
if (!System.IO.File.Exists(filePath))
{
context.Response.StatusCode = 401;
context.Response.End();
return;
}
//finish the response by transmitting the file
context.Response.StatusCode = 200;
context.Response.TransmitFile(filePath);
context.Response.Flush();
context.Response.End();
}
To call this handler you can simply set the src of the image to a path similar to /DynamicImage.ashx?username=johndoe.
Now your requirement may be slightly different. For example you may be retrieving the image from the database as a byte[] therefore instead of using the context.Response.TransmitFile() method you may wish to use the context.Response.BinaryWrite() method. This method transmits a byte[] as the response stream.
Finally I would refer you to another post (of mine) that talks about caching these images from a client perspective. This is very helpful if your button will be generated quite frequently. Leverage browser caching in IIS (google pagespeed issue)
It can be something as simple as
<asp:ImageButton ID="ImageButton1" runat="server" ImageUrl="~/arrow-down.gif" OnClick="ImageButton1_Click" />
and code behind:
protected void ImageButton1_Click(object sender, ImageClickEventArgs e)
{
// do some DB processing here
ImageButton1.ImageUrl = "~/arrow-up.gif";
}
If I understand what you are asking.
To put it under the page load would look something like:
private void Page_Load()
{
if(!Page.IsPostBack)
{
// perform db processing here
ImageButton.ImageUrl = "~/arrow-up.gif";
}
}
is all that is needed. Setting the ImageUrl line can be put wherever you need it.

Can gzip compression be selectively disabled in ASP.NET/IIS 7?

I am using a long-lived asynchronous HTTP connection to send progress updates to a client via AJAX. When compression is enabled, the updates are not received in discrete chunks (for obvious reasons). Disabling compression (by adding a <urlCompression> element to <system.webServier>) does solve the problem:
<urlCompression doStaticCompression="true" doDynamicCompression="false" />
However, this disables compression site-wide. I would like to preserve compression for every other controller and/or action except for this one. Is this possible? Or am I going to have to create a new site/area with its own web.config? Any suggestions welcome.
P.S. the code that does the writing to the HTTP response is:
var response = HttpContext.Response;
response.Write(s);
response.Flush();
#Aristos' answer will work for WebForms, but with his help, I've adapted a solution more inline with ASP.NET/MVC methodology.
Create a new filter to provide the gzipping functionality:
public class GzipFilter : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
var context = filterContext.HttpContext;
if (filterContext.Exception == null &&
context.Response.Filter != null &&
!filterContext.ActionDescriptor.IsDefined(typeof(NoGzipAttribute), true))
{
string acceptEncoding = context.Request.Headers["Accept-Encoding"].ToLower();;
if (acceptEncoding.Contains("gzip"))
{
context.Response.Filter = new GZipStream(context.Response.Filter, CompressionMode.Compress);
context.Response.AppendHeader("Content-Encoding", "gzip");
}
else if (acceptEncoding.Contains("deflate"))
{
context.Response.Filter = new DeflateStream(context.Response.Filter, CompressionMode.Compress);
context.Response.AppendHeader("Content-Encoding", "deflate");
}
}
}
}
Create the NoGzip attribute:
public class NoGzipAttribute : Attribute {
}
Prevent IIS7 from gzipping using web.config:
<system.webServer>
...
<urlCompression doStaticCompression="true" doDynamicCompression="false" />
</system.webServer>
Register your global filter in Global.asax.cs:
protected void Application_Start()
{
...
GlobalFilters.Filters.Add(new GzipFilter());
}
Finally, consume the NoGzip attribute:
public class MyController : AsyncController
{
[NoGzip]
[NoAsyncTimeout]
public void GetProgress(int id)
{
AsyncManager.OutstandingOperations.Increment();
...
}
public ActionResult GetProgressCompleted()
{
...
}
}
P.S. Once again, many thanks to #Aristos, for his helpful idea and solution.
I found a much easier way to do this. Instead of selectively doing your own compression, you can selectively disable the default IIS compression (assuming its enabled in your web.config).
Simply remove the accept-encoding encoding header on the request and IIS wont compress the page.
(global.asax.cs:)
protected void Application_BeginRequest(object sender, EventArgs e)
{
try
{
HttpContext.Current.Request.Headers["Accept-Encoding"] = "";
}
catch(Exception){}
}
What about you set the gzip compression by your self, selectivle when you wish for ? On the Application_BeginRequest check when you like to make and when you dont make compression. Here is a sample code.
protected void Application_BeginRequest(Object sender, EventArgs e)
{
string cTheFile = HttpContext.Current.Request.Path;
string sExtentionOfThisFile = System.IO.Path.GetExtension(cTheFile);
if (sExtentionOfThisFile.Equals(".aspx", StringComparison.InvariantCultureIgnoreCase))
{
string acceptEncoding = MyCurrentContent.Request.Headers["Accept-Encoding"].ToLower();;
if (acceptEncoding.Contains("deflate") || acceptEncoding == "*")
{
// defalte
HttpContext.Current.Response.Filter = new DeflateStream(prevUncompressedStream,
CompressionMode.Compress);
HttpContext.Current.Response.AppendHeader("Content-Encoding", "deflate");
} else if (acceptEncoding.Contains("gzip"))
{
// gzip
HttpContext.Current.Response.Filter = new GZipStream(prevUncompressedStream,
CompressionMode.Compress);
HttpContext.Current.Response.AppendHeader("Content-Encoding", "gzip");
}
}
}

Setting Context.Response.StatusCode does not seem to work

I have an HttpHandler with the following code:
using System;
using System.Web;
using Company.Cms;
using Company.Web.Handlers.Console;
namespace Company.Web.Handlers
{
/// <summary>
/// Summary description for AdminHandler
/// </summary>
public class AdminHandler : IHttpHandler
{
public bool IsReusable
{
get
{
return false;
}
}
public void ProcessRequest(HttpContext context)
{
HttpRequest request = context.Request;
HttpResponse response = context.Response;
string action = request.QueryString["action"];
if (!HttpContext.Current.User.CanAdminister())
{
response.StatusCode = 403;
response.Status = "403 Access Denied";
response.End();
return;
}
if (String.IsNullOrEmpty(action))
{
response.StatusCode = 404;
response.Status = "404 Not Found";
response.End();
return;
}
IHttpHandler handler = null;
switch (action)
{
case "menu":
handler = new MenuHandler();
break;
case "tree":
handler = new TreeHandler();
break;
case "grid":
handler = new GridHandler();
break;
case "list":
handler = new ListHandler();
break;
case "drop":
handler = new DropHandler();
break;
case "edit":
handler = new EditHandler();
break;
case "new":
handler = new InsertHandler();
break;
}
if (handler == null)
{
response.StatusCode = 404;
response.Status = "404 Not Found";
response.End();
}
else
{
handler.ProcessRequest(context);
}
}
}
}
Unfortunately when I intentionally specify an invalid action, the browser just displays a blank page. Non of the browser error messages are displayed both in Firefox and IE.
What could I be doing wrong?
EDIT - IE shows the error message, but Firefox does not.
First Try this:
protected void Page_Load(object sender, EventArgs e)
{
Response.StatusCode = 404;
Response.SuppressContent = true;
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
:)~
Firebug shows the correct status. Does
this mean that if I want the browser
to display a message, I have to render
it myself? – deverop
Absolutely it does. What the browser does based on an error code received is up to the browser. But you can still provide HTML to go along with the 404. Case in point... take a look at Stack Overflow's 404 page. That error message is entirely hand crafted.
Typically, however, you want to limit the amount of data returned from an error status; the more data you return from an erroneous request, the larger the surface of attack for denial of service.
I had a similar problem, which occures in IIS 7.0 only. What you could also try is to set
Response.TrySkipIisCustomErrors = true;
For 301 redirects use Response.RedirectPermanent().
For 302 redirects use Response.Redirect()
if (isPermanentRedirect)
{
// 301 Redirect
args.HttpContext.Response.RedirectPermanent(targetUrl);
}
else
{
// 302 Redirect
args.HttpContext.Response.Redirect(targetUrl);
}

Categories

Resources