Creating an embedded image button in ASP.net? - c#

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.

Related

How can I read uploaded file in CefSharp?

User uses my browser based on CefSharp. He uploads a file (which is selected in file input HTML control) to known server using XMLHttpRequest (it's JavaScript object for AJAX requests). I want to intercept and to read the uploading file in my browser.
I do the same in my browser based on Awesomium using IResourceInterceptor. It's easy, because ResourceRequest parameter contains full local path of the file. How can I do the same in CefSharp browser?
How user uploads file using XMLHttpRequest (JavaScript):
var file = document.getElementById('fileInput').files[0];
var formData = new FormData();
formData.append('file', file);
var xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.open('POST', '/upload', true);
xhr.send(formData);
Awesomium way to intercept user's file (C#):
class MyResourceInterceptor : IResourceInterceptor
{
public ResourceResponse OnRequest(ResourceRequest request)
{
// intercept URL with /upload path only
if (request.Url.AbsolutePath != "/upload")
{
return null;
}
// full local path for user's file
var filePath = request[1].FilePath;
// now I can read and process the file
}
public bool OnFilterNavigation(NavigationRequest request)
{
return false;
}
}
CefSharp doesn't currently expose a way to access Post Data which is what I'm guessing you require.
I have implemented a PR that contains a basic implementation, feel free to test it out. See https://github.com/cefsharp/CefSharp/pull/1113
The other option you have is implement OnFileDialog, you'd have to display your own dialog, simple enough though.
https://github.com/cefsharp/CefSharp/blob/cefsharp/41/CefSharp/IDialogHandler.cs#L38

Is this a safe way to get body of a HttpContext request

public static class HttpRequestHelper
{
public static string RequestBody()
{
var bodyStream = new StreamReader(HttpContext.Current.Request.InputStream);
bodyStream.BaseStream.Seek(0, SeekOrigin.Begin);
var bodyText = bodyStream.ReadToEnd();
return bodyText;
}
}
I plan to call this from ActionFilters to log incoming requests. Of course there could be multiple simultaneous requests.
Is this approach ok?
Is your question from the perspective of concurrency or ASP.NET Web API in general? Every request has its own context and you are okay with multiple requests going on in parallel. But here are two things for you to look at.
(1) Since you are using HttpContext, you are locking yourself to web hosting (IIS), which in many cases should be okay. But I would like you to be aware of this.
(2) Your code HttpRequestHelper.RequestBody() will work when called from an action filter, as you mentioned. However, if you try to call this from other places, say a message handler, this will not work. When I say this will not work, parameter binding that binds request body to action method parameter will not work. You will need to seek to the beginning once you are done. The reason it works from action filter is that binding would have already happened by the time action filter runs in the pipeline. This is another thing you might need to be aware of.
I've needed use InputStream of Http Request. I have a WebApp and IOS App that navigates to a aspx page, if the url request contains some parameters i read the information in database and if i not find any parameters in url request i read the request body and i work fine !
protected void Page_Load(object sender, EventArgs e)
{
try
{
if (string.IsNullOrEmpty(Request.QueryString["AdHoc"]) == false)
{
string v_AdHocParam = Request.QueryString["AdHoc"];
string [] v_ListParam = v_AdHocParam.Split(new char[] {','});
if (v_ListParam.Length < 2)
{
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(WS_DemandeIntervention));
WS_DemandeIntervention response = (WS_DemandeIntervention)jsonSerializer.ReadObject(Request.InputStream);
....
}
if (string.IsNullOrEmpty(Request.QueryString["IdBonDeCommande"])==false)
{
....

Call another aspx page in a different application

I have 2 different system, lets say SystemA and SystemB.
In SystemB, there is page, say calculate.aspx, where it receive certain parameter and will perform some calculation. This page doesn't display and info, and only serves to execute the code behind.
Now i have a page in SystemA, lets say execute.aspx, that will need to call calculate.aspx in SystemB to run the desired calculation. I cannot use redirect, since that will redirect me to the calculation.aspx page on SystemB.
I had tried using HttpWebRequest but it doesn't call to the page. The code is as below:
HttpWebRequest myRequest =
(HttpWebRequest)WebRequest.Create(nUrl + '?' + fn);
myRequest.Method = "GET";
WebResponse response = myRequest.GetResponse();
Does anyone know what is the correct way of doing it? Thanks.
EDIT
Manage to get it done after changing my codes to above. Thank you all.
You can either use a web service which would be the preferred way or use AJAX to send data to the page and get result in response.
I am probably missing something obvious here, but I'm puzzled by the whole part about the data and content which I'm not used to see in a GET Request.
You should, at your choice :
convert your request to POST
remove the part concerning the data
try this
namespace SampleService // this is service
{
public class Service1 : IService1
{
public string GetMessage()
{
return "Hello World";
}
public string GetAddress()
{
return "123 New Street, New York, NY 12345";
}
}
}
protected void Page_Load(object sender, EventArgs e) // calling the service
{
using (ServiceClient<IService1> ServiceClient =
new ServiceClient<IService1>("BasicHttpBinding_IService1"))
{
this.Label1.Text = ServiceClient.Proxy.GetMessage();
//once you have done the build inteli sense
//will automatically gets the new function
this.Label2.Text = ServiceClient.Proxy.GetAddress();
}
}
refer this link
http://www.codeproject.com/Articles/412363/How-to-Use-a-WCF-Service-without-Adding-a-Service
You can create a WebMethod in your application then you call this WebMethod from any other application, you can return Json serializable or XML data from this WebMethod

Accessing the protected area of an asp.net website via a System.Net.WebClient

I have a website running asp.net 2.0 with url authentication. There is a protected region of the website that requires users to log in to gain access to protected files. Is it possible to do the same thing using a System.Net.WebClient object to download a file in the protected area?
If you try to manually type in the url to a protected file, resource, page, etc it forwards you to the login page. I also get the html for the login page inside of "protectedFile.zip" whenever I execute the code below.
public void test()
{
try
{
using (var client = new CookieAwareWebClient())
{
//Not sure which name values to include, so I used what was in the post output in Firefox's firebug.
var values = new NameValueCollection
{
{ "ctl00$ContentPlaceHolder1$Login1$UserName", "testUsername" },
{ "ctl00$ContentPlaceHolder1$Login1$Password", "testPassword" }
};
retValue = client.UploadValues("www.test.com/login.aspx", values);
//retValue contains the login page?
Console.WriteLine(ASCIIEncoding.ASCII.GetString(retValue));
// If the previous call succeeded we now have a valid authentication cookie??
client.DownloadFile("www.test.com/protected/protectedFile.zip", "protectedFile.zip");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
Console.WriteLine(ASCIIEncoding.ASCII.GetString(retValue));
}
}
public class CookieAwareWebClient : WebClient
{
public CookieAwareWebClient()
{
CookieContainer = new CookieContainer();
}
public CookieContainer CookieContainer { get; private set; }
protected override WebRequest GetWebRequest(Uri address)
{
var request = (HttpWebRequest)base.GetWebRequest(address);
request.CookieContainer = CookieContainer;
return request;
}
}
I have looked at the following related questions but none of them have a final solution that I can understand.
asp.net Download files from protected server
How do I authenticate a WebClient request?
C# WebClient Log onto Website
WebClient accessing page with credentials
Can't login into asp.net website with WebClient
Any help would be appreciated!
If you are trying to "spoof" an ASP.Net Web Forms Postback, you will run into issues that will prevent you from doing so. You have to deal with VIEWSTATE and EVENTVALIDATION
The __EVENTVALIDATION hidden field is a security measure new to ASP.NET 2.0. The feature prevents unauthorized requests sent by potentially malicious users from the client. To ensure that each and every postback and callback event originates from the expected user interface elements, the page adds an extra layer of validation on events.

Prevent back button

I am using Razor on ASP.NET MVC with C#.
I am calling an external web page to process a credit card and it returns to me. I then display a receipt.
I'd like to prevent them from going back to the previous screen.
I do not have an underlying cs page, like asp since these are .cshtml files, to grab the event.
This receipt page is a View so I cannot put JavaScript in the header since it would affect every page using it.
Anyone know how I prevent the back button in this circumstance?
One possibility is to exclude the page you don't want to get back to from caching on the client. This could be done by setting the proper response headers. Here's an example with a [NoCache] custom action filter which you could use to decorate the corresponding controller action.
Firstly, if the previous page posted data to the server, best to Redirect(...) to another action after the successful processing, to avoid the data being resubmitted on "Refresh".
Then also set the page to expire, so the back button doesn't work:
https://stackoverflow.com/a/5352953/864763
You're asking the wrong question. Don't try to disable "back" on the client. This will be doomed to fail; you may be able to make it harder, but you'll never win that fight. Instead you should re-write the particular page that you have such that it will only ever process the credit card once. You should (on the server) "remember" that you've processed the credit card so that if the user goes back to the page to resubmit it you can just give them an error message saying "you have already submitted this information, you cannot submit this request twice".
Now, there are several ways of accomplishing this general goal, and some are better than others, but that's the goal you need to strive towards.
One way to do this is to go to every page that will redirect the user to this credit card form; just before submitting the request add something to that user's session (i.e. "pendingCreditCardSubmission" = true) Once they submit that request you then check for that session variable. If it's true, submit the request and set it to false, if it's false or not there then send an error message to the user.
This is how we did it:
public class NoBackFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.ExpiresAbsolute = DateTime.Now;
filterContext.HttpContext.Response.Expires = 0;
filterContext.HttpContext.Response.CacheControl = "no-cache";
filterContext.HttpContext.Response.Buffer = true;
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow);
filterContext.HttpContext.Response.Cache.SetNoStore();
filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
if (!filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.HttpContext.Request.HttpMethod != "POST" && !filterContext.Controller.ControllerContext.IsChildAction)
{
var after = filterContext.HttpContext.Request.RawUrl;
var session = GetSession(filterContext);
if (session["Current"] != null)
{
if (session["Before"] != null && session["Before"].ToString() == after)
filterContext.HttpContext.Response.Redirect(session["Current"].ToString());
else
{
session["Before"] = session["Current"];
session["Current"] = after;
}
}
else
{
session["Current"] = after;
}
}
base.OnActionExecuting(filterContext);
}
private HttpSessionStateBase GetSession(ActionExecutingContext context)
{
return context.HttpContext.Session;
}
}
After this you can implement it either in the general scope or in the controller scope.
It has been long since this was asked, but my fix was adding the [NoCache] above the WebPageController class.
[NoCache]
public class WebPageController : Controller
{
public JsonResult JsonError(Exception exception)
{
if (exception == null) throw new ArgumentNullException("exception");
Response.StatusCode = 500;
return new JsonResult
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = new
{
error = true,
success = false,
message = exception.Message,
detail = exception.ToString()
}
};
}
in MVC aspnet framework, you may choose to RedirectToActionPermanent
Which then it tells the browser 301 response code.
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllerbase.redirecttoactionpermanent?view=aspnetcore-5.0

Categories

Resources