I'm targeting a web service that takes a single string parameter.
On a schedule I want to fire off approximately 100 calls to that web service for 100 values from my database.
To optimise the process I believe I need to do the WebRequest calls asynchronously.
I've come across the code example below on a variety of blogs etc. but can't figure out how to adapt it for my requirement.
How can I wrap up the RegisterAsyncTask inside a foreach loop, parsing through the uri for the WebRequest.Create() that's inside BeginAsyncOperation?
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Net;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
public partial class AsyncPageTask : System.Web.UI.Page
{
private WebRequest _request;
protected void Page_Load(object sender, EventArgs e)
{
PageAsyncTask task = new PageAsyncTask(
new BeginEventHandler(BeginAsyncOperation),
new EndEventHandler(EndAsyncOperation),
new EndEventHandler(TimeoutAsyncOperation),
null
);
RegisterAsyncTask(task);
}
IAsyncResult BeginAsyncOperation(object sender, EventArgs e,
AsyncCallback cb, object state)
{
_request = WebRequest.Create("http://msdn.microsoft.com");
return _request.BeginGetResponse(cb, state);
}
void EndAsyncOperation(IAsyncResult ar)
{
string text;
using (WebResponse response = _request.EndGetResponse(ar))
{
using (StreamReader reader =
new StreamReader(response.GetResponseStream()))
{
text = reader.ReadToEnd();
}
}
Output.Text = text;
}
void TimeoutAsyncOperation(IAsyncResult ar)
{
Output.Text = "Data temporarily unavailable";
}
}
My intention is to write the response string back into a database. Appreciate this is an additional question but, is there any reason not to include the insert method call within the EndAsyncOperation method ?
This Q&A hints towards my main question but which 4th argument?
First you need to add this to your Web.config file (default is just 2):
<configuration>
<system.net>
<connectionManagement>
<add address="*" maxconnection="100" />
</connectionManagement>
<system.net>
<configuration>
Then you need to add async directive to your page: <%# Page Async="true" %>
protected void Page_Load(object sender, EventArgs e)
{
//...first get UriStringArray from db, and then:
foreach(string uri in UriStringArray)
{
var task = new PageAsyncTask(
new BeginEventHandler(BeginAsyncOperation),
new EndEventHandler(EndAsyncOperation),
new EndEventHandler(TimeoutAsyncOperation),
uri,
true; //run in parallel
);
RegisterAsyncTask(task);
}
}
IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback cb, object state)
{
var request = (HttpWebRequest)WebRequest.Create((string)state);
return request.BeginGetResponse(cb, request);
}
void EndAsyncOperation(IAsyncResult ar)
{
string text;
var request = (HttpWebRequest)ar.State;
using(WebResponse response = request.EndGetResponse(ar))
{
using(StreamReader reader = new StreamReader(response.GetResponseStream()))
text = reader.ReadToEnd();
}
//yes, you can insert in db here, even as a new PageAsyncTask - but then must call ExecuteRegisteredAsyncTasks() manually...
}
Related
With the auto generated code for VS 2013 for web forms, it adds CSRF protection. Do I need to do anything else to get it to work?
It says the token is added to Page.ViewStateUserKey. How am I suppose to check the ViewState? The debugger says it's null.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication12
{
public partial class SiteMaster : MasterPage
{
private const string AntiXsrfTokenKey = "__AntiXsrfToken";
private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
private string _antiXsrfTokenValue;
protected void Page_Init(object sender, EventArgs e)
{
// The code below helps to protect against XSRF attacks
var requestCookie = Request.Cookies[AntiXsrfTokenKey];
Guid requestCookieGuidValue;
if (requestCookie != null && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
{
// Use the Anti-XSRF token from the cookie
_antiXsrfTokenValue = requestCookie.Value;
Page.ViewStateUserKey = _antiXsrfTokenValue;
}
else
{
// Generate a new Anti-XSRF token and save to the cookie
_antiXsrfTokenValue = Guid.NewGuid().ToString("N");
Page.ViewStateUserKey = _antiXsrfTokenValue;
var responseCookie = new HttpCookie(AntiXsrfTokenKey)
{
HttpOnly = true,
Value = _antiXsrfTokenValue
};
if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
{
responseCookie.Secure = true;
}
Response.Cookies.Set(responseCookie);
}
Page.PreLoad += master_Page_PreLoad;
}
protected void master_Page_PreLoad(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Set Anti-XSRF token
ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ?? String.Empty;
}
else
{
// Validate the Anti-XSRF token
if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
|| (string)ViewState[AntiXsrfUserNameKey] != (Context.User.Identity.Name ?? String.Empty))
{
throw new InvalidOperationException("Validation of Anti-XSRF token failed.");
}
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
}
I downloaded Asp.net ViewState Helper. And because I was using 4.5 framework uses a different cyprtoscheme, I had to edit the web.config.
I added this:
<system.web>
<machineKey compatibilityMode="Framework20SP1" />
</system.web>
Then I was able use Fiddler and decrypt the View State and confirmed that the XSRF token is added.
This is the code to my Master Page cs file. For some reason when I run my default page, I get an error that says "object reference not set to an instance of an object."
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Theming.MasterPages
{
public partial class Main : System.Web.UI.MasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
string selectedTheme = Page.Theme;
HttpCookie preferredTheme = Request.Cookies.Get("PreferredTheme");
if (preferredTheme != null)
{
selectedTheme = preferredTheme.Value;
}
if (!string.IsNullOrEmpty(selectedTheme))
{
ListItem item = ThemeList.Items.FindByValue(selectedTheme);
if (item != null)
{
item.Selected = true;
}
}
}
switch (Page.Theme.ToLower())
{
case "darkgrey":
Menu1.Visible = false;
TreeView1.Visible = true;
break;
default:
Menu1.Visible = true;
TreeView1.Visible = false;
break;
}
}
protected void ThemeList_SelectedIndexChanged(object sender, EventArgs e)
{
HttpCookie preferredTheme = new HttpCookie("PreferredTheme");
preferredTheme.Expires = DateTime.Now.AddMonths(3);
preferredTheme.Value = ThemeList.SelectedValue;
Response.Cookies.Add(preferredTheme);
Response.Redirect(Request.Url.ToString());
}
}
}
The error appears to be at the switch statement but I can't figure out why. I've read on other posts that the value is assigning to the variable as null but I don't know why; I've got dark grey as an app theme. If anyone could please help me it would be very much appreciated.
I don't see Menu1 or TreeView1 defined anywhere in your markup. If those are in a content page, you can't access those in the MasterPage code-behind (there may be a way, but you can't directly access them the way you're trying to).
I am trying to run the following HTTP POST API Call using ASP.NET on Visual studio 2013. I created a new web application project as mentioned here
using System;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
CreateNewAPICall("test api abc");
}
private object CreateNewAPICall(string apiDesc)
{
object result = null;
var accessKey = "myaccesskey";
var secretKey = "mysecretkey";
var uRLapiList = "http://myurl.com";
byte[] bytes = Encoding.UTF8.GetBytes("apiListDesc=" + apiDesc);
var method = "POST";
var timeString = DateTime.UtcNow.GetDateTimeFormats()[104];
var signature = GetSignature(secretKey, method, timeString);
var authorization = accessKey + ":" + signature;
HttpWebRequest request = CreateWebRequest(uRLapiList, "POST", bytes.Length, timeString, authorization);
using (var requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode == HttpStatusCode.OK)
{
var responseReader = new StreamReader(request.GetResponse().GetResponseStream());
// Return List api Data
result = responseReader.ReadToEnd();
}
}
return result;
}
private HttpWebRequest CreateWebRequest(string endPoint, string method, Int32 contentLength, string timeString, string authorization)
{
// Some code here
}
private string GetSignature(string secretKey, string method, string timeString)
{
// Some code here
}
private byte[] HMAC_SHA1(string signKey, string signMessage)
{
// Some code here
}
private string CreateSignature(string stringIn, string scretKey)
{
// Some code here
}
}
Right now, I am confused as to where to put this file in the "Solution Explorer" in order to
run the file and get the output on my browser?
Right now I have this code inside "Models-->Class1.cs" directory as shown in the image below:
So, when I press F-5 key, I am getting directed to the home page of the ASP.NET with the URL http://localhost:4439/
Do I need to make any changes here?
I have an ASP.NET MVC application that uses SSRS for reporting (using a web form and report viewer). I would like to pass two parameters dynamically to the remote report. My current implementation stores the parameters in session, which works fine on VS Development Server, but the variable is null on IIS, upon retrieval in the web form.
Here is the controller method that calls the view
public ActionResult ShowReport(string id)
{
var reportParameters = new Dictionary<string, string>();
reportParameters.Add("Param1", id);
reportParameters.Add("Param2", "user1");
Session["reportParameters"] = reportParameters;
return View("ReportName");
}
And here is how I attempt to retrieve the parameters from the web form
protected void Page_Load(object sender, EventArgs e)
{
var reportParameters = (Dictionary<string, string>)Session["reportParameters"];
foreach (var item in reportParameters)
{
ReportParameter rp = new ReportParameter(item.Key, item.Value);
ReportViewer1.ServerReport.SetParameters(rp);
}
}
Anyone know why Session["reportParameters"] is null?
Or is there some other way of passing these parameters?
You can do it too:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
try
{
var js = new JavaScriptSerializer();
string reportPath= Request.QueryString["LocalReport"];
string parametersTemp = Request.QueryString["ParametersReport"];
List<ReportParameter> parameters = null;
if (parametrosTemp != "")
{
parameters = JsonConvert.DeserializeObject
<List<ReportParameter>>(parametrosTemp);
}
GenerateReport(reportPath, parameters );
}
catch (Exception ex) {
statusReport.Value = ex.Message;
}
}
}
private void GenerateReport(string reportPath, List<ReportParameter> reportParameters)
{
reportCurrent.ProcessingMode = ProcessingMode.Remote;
ServerReport serverReport = reportCurrent.ServerReport;
serverReport.ReportServerUrl =
new Uri(AppSettings.URLReportServer);
serverReport.ReportPath = reportPath;
serverReport.Refresh();
if (reportParameters != null)
{
reportCurrent.ServerReport.SetParameters(reportParameters);
}
}
Is the problem that Session["reportParameters"] is null or is it that you don't get any parameters added to your report? Because your code, as it stands, won't add parameters to your report even if you pass them across properly and so the report parameters will be null.
SetParameters takes IEnumerable<ReportParameter> (usually a List), not a ReportParameterobject. Your code should look more like this:
protected void Page_Load(object sender, EventArgs e)
{
var reportParameters = (Dictionary<string, string>)Session["reportParameters"];
List<ReportParameter> parameters = new List<ReportParameter>();
foreach (var item in reportParameters)
{
parameters.Add(new ReportParameter(item.Key, item.Value););
}
ReportViewer1.ServerReport.SetParameters(parameters);
}
My questions are:
So I need to create a custom class / HttpHandler and throw this code in it? Or can I place this somewhere else like in the global.asax?
How do I check for the Host (so check for www.mydomain.com) incoming so I know when to redirect?
Code:
if ("comes from certain domain")
{
context.Response.Status = "301 Moved Permanently";
context.Response.AddHeader("Location", "http://www.testdomain.com/Some.aspx");
}
Paste this into a new .cs file in your App_Code folder:
using System;
using System.Web;
public class TestModule : IHttpModule
{
public void Init(HttpApplication context) {
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e) {
HttpApplication app = (HttpApplication)sender;
if (app.Request.Url.Host == "example.com") {
app.Response.Status = "301 Moved Permanently";
app.Response.AddHeader("Location", "http://www.testdomain.com/Some.aspx");
}
}
public void Dispose() {
}
}
Then add this to your web.config in system.web:
<httpModules>
<add type="TestModule" name="TestModule" />
</httpModules>
You should be able to place it in the Global.asax, in the Application_BeginRequest event.
protected void Application_BeginRequest(Object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
string host = context.Request.Url.Host;
if (host == "www.mydomain.com")
{
context.Response.Status = "301 Moved Permanently";
context.Response.AddHeader("Location",
"http://www.testdomain.com/Some.aspx");
}
}
I avoid putting anything unnecessary in global.asax as it tends to get cluttered. Instead, create an HttpModule, add an event handler
public void Init(System.Web.HttpApplication app)
{
app.BeginRequest += new System.EventHandler(Rewrite_BeginRequest);
}
and, in the beginRequest method,
public void Rewrite_BeginRequest(object sender, System.EventArgs args)
{
HttpApplication app = (HttpApplication)sender;
/// all request properties now available through app.Context.Request object
}