In WCF (System.Net.WebHeaderCollection) a header value can be retreived using either the System.Net.HttpRequestHeader enum or a header string:
WebOperationContext.Current.IncomingRequest.Headers[httpRequestHeaderEnum]
// or
WebOperationContext.Current.IncomingRequest.Headers.Get(rawHeaderString)
But in ASP.NET, the headers are in a NameValueCollection which only accepts a header string:
HttpContext.Current.Request.Headers[rawHeaderString]
In order to use the Enum's for ASP.NET, where is the map from enum System.Net.HttpRequestHeader to its header string?
How about writing a mapping method? For reference:
HttpRequestHeader enumeration
You could just make a mapping table, or Using code swiped from Binary Worrier's post, you could do something like this:
public static string TranslateToHttpHeaderName(HttpRequestHeader enumToTranslate)
{
const string httpHeaderNameSeparator = "-";
string enumName = enumToTranslate.ToString();
var stringBuilder = new StringBuilder();
// skip first letter
stringBuilder.Append(enumName[0]);
for (int i = 1; i < enumName.Length; i++)
{
if (char.IsUpper(enumName[i])) stringBuilder.Append(httpHeaderNameSeparator);
stringBuilder.Append(enumName[i]);
}
// Cover special case for 2 character enum name "Te" to "TE" header case.
string headerName = stringBuilder.ToString();
if (headerName.Length == 2) headerName = headerName.ToUpper();
return headerName;
}
You can use a default implementation, using a WebHeaderCollection
private static readonly ConcurrentDictionary<HttpRequestHeader, string> ToStringKeyCache = new ConcurrentDictionary<HttpRequestHeader, string>();
public static string ToStringKey(this HttpRequestHeader enumToEvaluate)
{
var str = ToStringKeyCache.GetOrAdd(enumToEvaluate, header =>
{
var nm = new WebHeaderCollection();
nm.Set(header, "X");
return nm.AllKeys.Single();
});
return str;
}
Unless I completely misunderstood your question:
Import the System.Net namespace: using System.Net;
e.g. WebForms:
using System.Net
protected void Page_Load(object sender, EventArgs e)
{
//Single - e.g. Connection
FooLabel.Text = Request.Headers[HttpRequestHeader.Connection.ToString()] + "<hr />";
//Go through all
foreach (var en in Enum.GetNames(typeof(HttpRequestHeader)))
{
FooLabel.Text += en + " : " + Request.Headers[en] + "<br />";
}
}
Hth...
Related
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'm using this tutorial https://web.archive.org/web/20211020001747/https://www.4guysfromrolla.com/articles/030211-1.aspx that’s uses a PDF template, lets the user input fields using textbox's. The file downloads onto the client’s pc but I would like to save a copy of the file into a sql database also or just save the file in the database instead of both.
protected void btnGeneratePDF_Click(object sender, EventArgs e)
{
var pdfPath = Path.Combine(Server.MapPath("~/PDFTemplates/fw9.pdf"));
// Get the form fields for this PDF and fill them in!
var formFieldMap = PDFHelper.GetFormFieldNames(pdfPath);
formFieldMap["topmostSubform[0].Page1[0].f1_01_0_[0]"] = txtName.Text;
formFieldMap["topmostSubform[0].Page1[0].f1_02_0_[0]"] = txtBusinessName.Text;
if (rblTaxClassification.SelectedValue != null)
{
var formFieldName = string.Format("topmostSubform[0].Page1[0].c1_01[{0}]", rblTaxClassification.SelectedIndex);
formFieldMap[formFieldName] = (rblTaxClassification.SelectedIndex + 1).ToString();
}
if (chkExemptPayee.Checked)
formFieldMap["topmostSubform[0].Page1[0].c1_01[7]"] = "8";
formFieldMap["topmostSubform[0].Page1[0].f1_04_0_[0]"] = txtAddress.Text;
formFieldMap["topmostSubform[0].Page1[0].f1_05_0_[0]"] = txtCityStateZIP.Text;
formFieldMap["topmostSubform[0].Page1[0].f1_07_0_[0]"] = txtAccountNumbers.Text;
// Requester's name and address (hard-coded)
formFieldMap["topmostSubform[0].Page1[0].f1_06_0_[0]"] = "Acme Website\n123 Anywhere Lane\nSpringfield, USA";
// SSN
if (!string.IsNullOrEmpty(txtSSN1.Text))
{
formFieldMap["topmostSubform[0].Page1[0].social[0].TextField1[0]"] = txtSSN1.Text;
formFieldMap["topmostSubform[0].Page1[0].social[0].TextField2[0]"] = txtSSN2.Text;
formFieldMap["topmostSubform[0].Page1[0].social[0].TextField2[1]"] = txtSSN3.Text;
}
else if (!string.IsNullOrEmpty(txtEIN1.Text))
{
formFieldMap["topmostSubform[0].Page1[0].social[0].TextField2[2]"] = txtEIN1.Text;
formFieldMap["topmostSubform[0].Page1[0].social[0].TextField2[3]"] = txtEIN2.Text;
}
var pdfContents = PDFHelper.GeneratePDF(pdfPath, formFieldMap);
PDFHelper.ReturnPDF(pdfContents, "Completed-W9.pdf");
FileStream fs = new FileStream(pdfPath, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
Byte[] bytes = br.ReadBytes((Int32)fs.Length);
br.Close();
fs.Close();
//insert the file into database
string strQuery = "insert into tblFiles(Name, ContentType, Data) values (#Name, #ContentType, #Data)";
SqlCommand cmd = new SqlCommand(strQuery);
cmd.Parameters.Add("#Name", SqlDbType.VarChar).Value = "Completed-W9132.pdf";
cmd.Parameters.Add("#ContentType", SqlDbType.VarChar).Value = "application/pdf";
cmd.Parameters.Add("#Data", SqlDbType.Binary).Value = bytes;
InsertUpdateData(cmd);
App_code/pdfHelper.cs
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Web;
using System.IO;
using iTextSharp.text.pdf;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
public class PDFHelper
{
public static Dictionary<string, string> GetFormFieldNames(string pdfPath)
{
var fields = new Dictionary<string, string>();
var reader = new PdfReader(pdfPath);
foreach (DictionaryEntry entry in reader.AcroFields.Fields)
fields.Add(entry.Key.ToString(), string.Empty);
reader.Close();
return fields;
}
public static byte[] GeneratePDF(string pdfPath, Dictionary<string, string> formFieldMap)
{
var output = new MemoryStream();
var reader = new PdfReader(pdfPath);
var stamper = new PdfStamper(reader, output);
var formFields = stamper.AcroFields;
foreach (var fieldName in formFieldMap.Keys)
formFields.SetField(fieldName, formFieldMap[fieldName]);
stamper.FormFlattening = true;
stamper.Close();
reader.Close();
return output.ToArray();
}
// See http://stackoverflow.com/questions/4491156/get-the-export-value-of-a-checkbox-using-itextsharp/
public static string GetExportValue(AcroFields.Item item)
{
var valueDict = item.GetValue(0);
var appearanceDict = valueDict.GetAsDict(PdfName.AP);
if (appearanceDict != null)
{
var normalAppearances = appearanceDict.GetAsDict(PdfName.N);
// /D is for the "down" appearances.
// if there are normal appearances, one key will be "Off", and the other
// will be the export value... there should only be two.
if (normalAppearances != null)
{
foreach (var curKey in normalAppearances.Keys)
if (!PdfName.OFF.Equals(curKey))
return curKey.ToString().Substring(1); // string will have a leading '/' character, so remove it!
}
}
// if that doesn't work, there might be an /AS key, whose value is a name with
// the export value, again with a leading '/', so remove it!
var curVal = valueDict.GetAsName(PdfName.AS);
if (curVal != null)
return curVal.ToString().Substring(1);
else
return string.Empty;
}
public static void ReturnPDF(byte[] contents)
{
ReturnPDF(contents, null);
}
public static void ReturnPDF(byte[] contents, string attachmentFilename)
{
var response = HttpContext.Current.Response;
if (!string.IsNullOrEmpty(attachmentFilename))
response.AddHeader("Content-Disposition", "attachment; filename=" + attachmentFilename);
response.ContentType = "application/pdf";
response.BinaryWrite(contents);
response.End();
}
}
The parts of the tutorial you're looking for in that case are right here:
Response.ContentType = "application/pdf";
Response.BinaryWrite(output.ToArray());
When saving a "file" to a database you essentially care about two (maybe three) things:
The byte array of the file contents
The type of the file
(Maybe a name for the file)
Since the tutorial concludes with two of these things (above), the type and the data, you can store these two things into your database however you need to store them. This depends on the database you're using, how you access that database, etc. Essentially to store these two things you just need a text column (varchar?) and a binary (or "blob") column (varbinary?).
The only difference is that instead of setting the type as a header in an HTTP response and writing the bytes to that HTTP response, you're using both of them as values in your database. Everything else is the same.
I have a fillable pdf. In which i have few textboxes.
I fill these fields by using following code(itextsharp).
DataTable dt = new DataTable();
String pdfPath1 = Server.MapPath("pdfs\\transmittal2.pdf");
if (File.Exists(pdfPath1))
{
dt = objClsTransmittal.GetTransmittal(jobid, cid);
String comment = "Correspondence generated for " + dt.Rows[0]["Recipient"].ToString();
var formfield = PDFHelper.GetFormFieldNames(pdfPath1);
formfield["DocDate"] = DateTime.Now.ToLongDateString();
formfield["Address1"] = dt.Rows[0]["Company"].ToString();
formfield["Address2"] = dt.Rows[0]["Address1"].ToString();
formfield["PropertyAddress"] = dt.Rows[0]["PropertyAddress"].ToString();
formfield["Job"] = dt.Rows[0]["JobID"].ToString();
formfield["Name"] = dt.Rows[0]["Recipient"].ToString();
formfield["CityStateZip"] = dt.Rows[0]["address2"].ToString();
formfield["E-mail"] = dt.Rows[0]["Email"].ToString();
var pdfcontent = PDFHelper.GeneratePDF(pdfPath1, formfield);
PDFHelper.ReturnPDF(pdfcontent, "Transmittal.pdf");
}
Currently its downloded as read only pdf.
when this pdf gets downloaded, i want that all fields still remain fillable, with the text i have filled in pdf. So that i can edit the text.
I'm looking forward for your replies.
Thanks.
EDIT
PdfHelper is my custom class. In which i have used following code:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Web;
using System.IO;
using iTextSharp.text.pdf;
public class PDFHelper
{
public static Dictionary<string, string> GetFormFieldNames(string pdfPath)
{
var fields = new Dictionary<string, string>();
var reader = new PdfReader(pdfPath);
foreach (DictionaryEntry entry in reader.AcroFields.Fields)
fields.Add(entry.Key.ToString(), string.Empty);
reader.Close();
return fields;
}
public static byte[] GeneratePDF(string pdfPath, Dictionary<string, string> formFieldMap)
{
var output = new MemoryStream();
var reader = new PdfReader(pdfPath);
var stamper = new PdfStamper(reader, output);
var formFields = stamper.AcroFields;
foreach (var fieldName in formFieldMap.Keys)
formFields.SetField(fieldName, formFieldMap[fieldName]);
stamper.FormFlattening = true;
stamper.Close();
reader.Close();
return output.ToArray();
}
public static string GetExportValue(AcroFields.Item item)
{
var valueDict = item.GetValue(0);
var appearanceDict = valueDict.GetAsDict(PdfName.AP);
if (appearanceDict != null)
{
var normalAppearances = appearanceDict.GetAsDict(PdfName.N);
if (normalAppearances != null)
{
foreach (var curKey in normalAppearances.Keys)
if (!PdfName.OFF.Equals(curKey))
return curKey.ToString().Substring(1); // string will have a leading '/' character, so remove it!
}
}
var curVal = valueDict.GetAsName(PdfName.AS);
if (curVal != null)
return curVal.ToString().Substring(1);
else
return string.Empty;
}
public static void ReturnPDF(byte[] contents)
{
ReturnPDF(contents, null);
}
public static void ReturnPDF(byte[] contents, string attachmentFilename)
{
var response = HttpContext.Current.Response;
if (!string.IsNullOrEmpty(attachmentFilename))
response.AddHeader("Content-Disposition", "attachment; filename=" + attachmentFilename);
response.ContentType = "application/pdf";
response.BinaryWrite(contents);
response.End();
}
Your code line
stamper.FormFlattening = true;
instructs iTextSharp to flatten the form fields, i.e. to integrate them into the page content and remove the form field annotations.
As you want to keep the form fields as editable fields, don't flatten the form.
Error: Cannot convert type in PDFHelper.cs
public static Dictionary<string, string> GetFormFieldNames(string pdfPath)
{
var fields = new Dictionary<string, string>();
var reader = new PdfReader(pdfPath);
foreach (DictionaryEntry entry in reader.AcroFields.Fields) //ERROR: 'System.Collections.Generic.KeyValuePair' to 'System.Collections.DictionaryEntry'
{
fields.Add(entry.Key.ToString(), string.Empty);
}
reader.Close();
return fields;
}
'System.Collections.Generic.KeyValuePair' to 'System.Collections.DictionaryEntry'
I've had some Page Tab apps working, just basic authorization as I don't need anything except name / id for what I'm doing - but I've tried the same method with the canvas app and it's not working. It seems to be with the redirect back, and I really can't see where I'm going wrong based on facebook's documentation for canvas apps http://developers.facebook.com/docs/appsonfacebook/tutorial/#auth
On loading I show a button, on clicking that it tries to get authorisation but it's not working. I've checked and double checked that I'm using the canvas url as the redirect but all I'm getting is a 404 (which is wrong as the page definitely exists, or else the button wouldn't appear). The URL on the 404 page is what really bemuses me, it's:
http://apps.mydomain.co.uk/myappname/https%3a%2f%2fwww.facebook.com%2fdialog%2foauth%3fclient_id%3d999999999999%26redirect_uri%3dhttp%253a%252f%252fapps.mydomain.co.uk%252fmyappname%252f
It has to be something to do with the redirection - any help would be appreciated.
Here's my code (shortened for clarity, urls changed):
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string error = Request.QueryString["error_reason"];
if (String.IsNullOrEmpty(error))
{
if (Request.Form["signed_request"] != null)
{
signedRequest();
}
if (String.IsNullOrEmpty(_auth))
{
intro.Visible = true;
main.Visible = false;
}
else
{
intro.Visible = false;
main.Visible = true;
}
}
else
{
// show intro page
intro.Visible = true;
main.Visible = false;
}
}
}
protected void Authorise_Click(object sender, EventArgs e)
{
// redirect if needs auth
if (String.IsNullOrEmpty(_auth))
{
// get authorisation
string id = "999999999999";
string canvas = Server.UrlEncode("http://apps.mydomain.co.uk/myappname/");
string redir = Server.UrlEncode("https://www.facebook.com/dialog/oauth?client_id="+ id +"&redirect_uri=" + canvas); // test
Response.Write("<script>top.location.href='" + redir + "'</script>");
}
else
{
// already authorised
// go straight to main page
}
}
private void signedRequest()
{
string sreq = Request.Form["signed_request"];
string[] splitPayload = sreq.Split('.');
string sig = splitPayload[0];
string payload = splitPayload[1];
Dictionary<string, string> JSONpayload = DecodePayload(payload);
_auth = JSONpayload["user_id"].ToString();
_code = JSONpayload["oauth_token"].ToString();
if (!String.IsNullOrEmpty(JSONpayload["oauth_token"]))
{
var fb = new FacebookClient(JSONpayload["oauth_token"]);
var result = (IDictionary<string, object>)fb.Get("/me");
_name = (string)result["name"];
//Response.Write("<br /><br />RESULT: " + result);
ViewState["name"] = _name;
Session["name"] = _name;
}
ViewState["id"] = _auth;
Session["id"] = _auth;
}
private Dictionary<string, string> DecodePayload(string payload)
{
var encoding = new UTF8Encoding();
var decodedJson = payload.Replace("=", string.Empty).Replace('-', '+').Replace('_', '/');
var base64JsonArray = Convert.FromBase64String(decodedJson.PadRight(decodedJson.Length + (4 - decodedJson.Length % 4) % 4, '='));
var json = encoding.GetString(base64JsonArray);
var jObject = JObject.Parse(json);
Response.Write("jObject: " + jObject);
var parameters = new Dictionary<string, string>();
parameters.Add("user_id", (string)jObject["user_id"] ?? "");
parameters.Add("oauth_token", (string)jObject["oauth_token"] ?? "");
var expires = ((long?)jObject["expires"] ?? 0);
parameters.Add("expires", expires > 0 ? expires.ToString() : "");
parameters.Add("profile_id", (string)jObject["profile_id"] ?? "");
if (jObject["page"] != null)
{
var jObjectPage = JObject.Parse(jObject["page"].ToString());
bool isPageLiked = bool.Parse(jObjectPage["liked"].ToString());
parameters.Add("is_Liked", isPageLiked.ToString() ?? "");
}
else
{
_liked = false;
}
return parameters;
}
Assuming a static method like below is called from ASP.NET page,
can a different thread(b) overwrite the value of s1 after the first line is executed by thread(a)?
If so, can assigning parameters to local variables before manipulation solve this?
public static string TestMethod(string s1, string s2, string s3)
{
s1 = s2 + s3;
....
...
return s1;
}
Is there are a simple way to recreate such thread safety related issues?
Thanks.
No, the parameters are local variables - they're independent of any other threads. As strings are also immutable, you're safe. If these were mutable - e.g. a parameter of StringBuilder s1 - then although the value of s1 (a reference) couldn't be changed, the object that the parameter referred to could change its contents.
ref and out parameters could potentially have issues, as they can alias variables which are shared between threads.
I had same confusion too and here is my test code. Just sharing it ...
public partial class _default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
ThreadTest b = new ThreadTest();
Thread t = new Thread(new ParameterizedThreadStart(ThreadTest.sum));
Thread t1 = new Thread(new ParameterizedThreadStart(ThreadTest.sum));
t.Start(10);
t1.Start(12);
}
}
class ThreadTest
{
public static void sum(object XX)
{
int x = (int)XX;
for (int i = 0; i < x; i++)
{
System.Diagnostics.Debug.WriteLine("max : " + x + " --- " + i.ToString());
}
}
}
... Now if you run this you will see that int x is safe. so local non static variables are safe for a process and can not crippled by multiple thread
Yes, under some condition, as seen by the example code.
public static class ConsoleApp {
public static void Main() {
Console.WriteLine("Write something.");
var str = Console.ReadLine();
if (String.IsNullOrEmpty(str))
return;
new Thread(() => TestMethod(null, str, "")).Start();
// Allow TestMethod to execute.
Thread.Sleep(100);
unsafe {
// Grab pointer to our string.
var gcHandle = GCHandle.Alloc(str, GCHandleType.Pinned);
var strPtr = (char*)gcHandle.AddrOfPinnedObject().ToPointer();
// Change it, one character at a time, wait a little more than
// TestMethod for dramatic effect.
for (int i = 0; i < str.Length; ++i) {
strPtr[i] = 'x';
Thread.Sleep(1100);
}
}
// Tell TestMethod to quit.
_done = true;
Console.WriteLine("Done.");
Console.ReadLine();
}
private static Boolean _done;
public static void TestMethod(String x, String y, String z) {
x = y + z;
while (!_done) {
Console.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(), x);
Thread.Sleep(1000);
}
}
}
Requirements (afaik)
Unsafe context to use pointers.
Use String.Concat(String str0, String str1) which is optimized for cases where str0 == String.Empty or str1 == String.Empty, which returns the non-empty string. Concatenating three or more strings would create a new string which blocks this.
Here's a fixed version of your modified one.
public static class ConsoleApp {
private static Int32 _counter = 10;
public static void Main() {
for (var i = 0; i < 10; i++) {
var str = GetString();
Console.WriteLine("Input: {0} - {1}", DateTime.Now.ToLongTimeString(), str);
new Thread(() => TestMethod(str)).Start();
unsafe {
var gcHandle = GCHandle.Alloc(str, GCHandleType.Pinned);
var strPtr = (char*)gcHandle.AddrOfPinnedObject().ToPointer();
strPtr[0] = 'A';
strPtr[1] = 'B';
strPtr[2] = 'C';
strPtr[3] = 'D';
strPtr[4] = 'E';
}
}
Console.WriteLine("Done.");
Console.ReadLine();
}
private static String GetString() {
var builder = new StringBuilder();
for (var i = _counter; i < _counter + 10; i++)
builder.Append(i.ToString());
_counter = _counter + 10;
return builder.ToString();
}
public static void TestMethod(Object y) {
Thread.Sleep(2000);
Console.WriteLine("Output: {0} {1}", DateTime.Now.ToLongTimeString(), y);
}
}
This still works because Object.ToString() is overriden in String to return this, thus returning the exact same reference.
Thanks Simon, here is the my evaluation on this.
In the following code, i spawn threads simply using Thread.Start and the output becomes inconsistent.
This is proving that string passed on to a method can be modified.
If otherwise please explain!
public static class ConsoleApp{
[ThreadStatic]
private static int counter = 10;
public static void Main()
{
string str;
object obj = new object();
// Change it, one character at a time, wait a little more than
// TestMethod for dramatic effect.
for (int i = 0; i < 10; i++)
{
lock (obj)
{
str = GetString();
Console.WriteLine(DateTime.Now.ToLongTimeString());
//ThreadPool.QueueUserWorkItem(TestMethod, str);
new Thread(() => TestMethod(str)).Start();
}
}
Console.WriteLine("Done.");
Console.ReadLine();
}
private static string GetString()
{
object obj = new object();
lock (obj)
{
StringBuilder sb = new StringBuilder();
int temp = 0;
for (int i = counter; i < counter + 10; i++)
{
sb.Append(i.ToString());
temp = i;
}
counter = temp;
return sb.ToString();
}
}
public static void TestMethod(object y)
{
Thread.Sleep(2000);
Console.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(), y.ToString());
}
}
Thanks.