Access to QueryString / Session from a static Method? - asp.net

I use ASP.Net and a static WebMethod / PageMethod to do some async work.
My question is how to access my queryStrings and Session variables here?
I tried "HttpContext.Current" and a lot of information is available here, but not my QueryString nor my Session and I don't know why.
[WebMethod(EnableSession=true)]
public static object Update(string time)
{
string timer;
string lastBidder;
string price;
//Countdown timer
DateTime dt = DateTime.Parse(time);
dt = dt.AddSeconds(-1.0);
timer = dt.ToString("HH:mm:ss");
int auctionID = 6;
if (!int.TryParse(HttpContext.Current.Request.QueryString["id"], out auctionID))
throw new Exception("Seitenaufruf ohne ID");
Business.AuctionHandling ah = new Business.AuctionHandling();
DAL.Auktion auktion = ah.GetSingleAuction(auctionID);
price = auktion.AktuellerPreis.ToString("###0.00");
//this.gvHistory.DataBind();
List<DAL.Biethistorie> his = ah.GetBidHistoryForAuction(auctionID);
if (his.Count > 0)
{
lastBidder = his[0].Benutzer.Benutzername;
//History fett
//gvHistory.Rows[0].Font.Bold = true;
//gvHistory.Rows[0].ForeColor = System.Drawing.ColorTranslator.FromHtml("#3B4D5F");
//lblHöchstesGebot.ForeColor = System.Drawing.Color.Black;
}
else
{
lastBidder = Helper.StringHelper.AuctionDeatil_NoBidder;
//lblHöchstesGebot.ForeColor = System.Drawing.Color.Red;
}
return new
{
valueTimer = timer,
valuePrice = price,
valueLastBidder = lastBidder
};
}

The QueryString is in the Request property.
System.Web.HttpContext.Current.Request.QueryString
But the Session is in there:
System.Web.HttpContext.Current.Session

Out of interest why aren't you just passing the information you need to the web method as you are calling it?

I had a similar problem. I had a number of static methods I was using to help manage my Cache and Session. Luckily, you can pass a reference to the Cache or Session into your moethods like this:
public static void DoSomething(System.Web.SessionState sessn)
And then access your session by using the sessn object.

THIS IS LATE REPLY BUT WILL HELP OTHERS AND MARK IT AS ANSWER ..well u have to post your code on how you are calling that Update method. coz i am doing the same and im getting my querystring and the trick for that is you have to pass that in alongwith your get or post call like following
$.ajax({
type: "POST",
url: "" + getDirectoryPath() + getCurrentPageName() + "/SavePatientEpisodes?ApplicationInstanceID=" + querystring,
data: JSON.stringify({ PatientOne: patientOneData, PatientTwo: patientTwoData, PatientOneID: $("#tbPatient1").val(), PatientTwoID: $("#tbPatient2").val() }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
// Replace the div's content with the page method's return.
}
});
AND ACCESS IT as BELOW
_
Public Shared Function SavePatientEpisodes(ByVal PatientOne As List(Of Episode), ByVal PatientTwo As List(Of Episode), ByVal PatientOneID As String, ByVal PatientTwoID As String) As String
Dim dd As String = HttpContext.Current.Request.QueryString("ApplicationInstanceID")
Dim lang As Integer = toInt(HttpContext.Current.Session("UserID"))
return ""
End Function

Related

Export to excel not working from HttpHandler J-Query AJAX

im have a weird problem whereby my functionality of exporting to excel doesnt seem to work.
im using J-Query and AJAX to pass html data to a http handler which has some simple context.Response code which all seems fine. Anyway, heres my code:
// my hyperlink for user to click
Click Here to Export
my J-Query/AJAX code
<script type="text/javascript">
$(document).ready(function () {
$("#hyperLink").click(function (e) {
var result = $('#output').html();
var newRes = result.replace('\n', '');
$.ajax({
url: "ExportToExcelhandler.ashx",
data: { 'htmlData': newRes },
dataType: "json",
type: "POST",
success: function (data) {
alert(data);
}
});
});
});
</script>
and my handler:
public void ProcessRequest(HttpContext context)
{
string htmlStuff = context.Request["htmlData"];
string trimStart = "";
string trimEnd = "";
if (htmlStuff != null)
{
trimStart = htmlStuff.Substring(75, htmlStuff.Length - 75);
trimEnd = trimStart.Remove(trimStart.Length - 8, 8) + "";
}
string final= trimEnd;
context.Response.Clear();
context.Response.Buffer = true;
context.Response.AddHeader("content-disposition", "attachment; filename=excelData.xls");
context.Response.ContentType = "application/vnd.ms-excel";
HttpResponse response = context.Response;
context.Response.Output.Write(finalHtmlData);
context.Response.Flush();
context.Response.End();
}
-- Granted, I'm doing some weird things with replace function in my J-Query, and Substring and Remove in my handler; this is because i had to trim my html data so that only the table with the data inside it was included (caused error otherwise). The html data is just report data. So the html data is passed fine to the handler, and it goes through the ProcessRequest method fine, yet doesn't export to excel. Any help would be greatly appreciated, thanks.
Split this into two HTTP handlers, one to generate the Excel data and the second to retrieve the data and have a resource point at it, like this:
GenerateExcelDocument HTTP handler code:
public void ProcessRequest(HttpContext context)
{
string htmlStuff = context.Request["htmlData"];
var docIdentifier = this.GenerateExcelDocument(htmlStuff);
context.Response.ContentType = "text/plain";
context.Response.Write(docIdentifier.ToString("N"));
}
private Guid GenerateExcelDocument()
{
var identifier = Guid.NewGuid();
string trimStart = "";
string trimEnd = "";
if (htmlStuff != null)
{
trimStart = htmlStuff.Substring(75, htmlStuff.Length - 75);
trimEnd = trimStart.Remove(trimStart.Length - 8, 8) + "";
}
// Logic that generates your document and saves it using the identifier
// Can save to database, file system, etc.
return identifier;
}
Now you can call this HTTP handler, like this:
$(document).ready(function () {
$("#hyperLink").click(function (e) {
var result = $('#output').html();
var newRes = result.replace('\n', '');
$.ajax({
url: "GenerateExcelDocument.ashx",
data: { 'htmlData': newRes },
dataType: "json",
type: "POST",
success: function (result) {
window.location.href = '/RetrieveExcelDocument.ashx/' + result;
}
});
});
});
Note: The success callback is where you can hook up the HTML resource to the file retrieval from the server (think href of the anchor tag that worked without passing data to the handler before).
Finally, we need to build the retrieval HTTP handler logic to actually get the Excel document, based upon the identifier returned from the GenerateExcelDocument HTTP handler call, like this:
RetrieveExcelDocument HTTP handler code:
public void ProcessRequest(HttpContext context)
{
var identifier = new Guid(context.Request.Url.Segments[1]);
// Get Excel document content from database, file system, etc. here
var fileContent = GetExcelDocument(identifier);
context.Response.AddHeader("content-disposition",
"attachment; filename=excelData.xls");
context.Response.ContentType = "application/vnd.ms-excel";
context.Response.OutputStream.Write(fileContent, 0, fileContent.Length);
}

stop old session list object to add up

what my code 'below' does is: the client javascript calls a webservice method which creates a generic list and then stores it into a session.
[WebMethod(EnableSession = true)]
public void SaveUserSelection(string slctdRooms, string slctdcst)
{
List<SelectRms> SelectR = Session["someinfo"] as List<SelectRms>;
if (SelectR == null)
{
SelectR = new List<SelectRms>();
Session["someinfo"] = SelectR;
}
SelectR.Add(new SelectRms { roomtype = slctdRooms, Roomcst = slctdcst });
}
I would then retreave the session to show the data in another page like this
List(SlctdRmWebSrv.SelectRms) SelctdRM = (List(SlctdRmWebSrv.SelectRms))Sessio["someinfo"];
if(SelctdRM != null)
{
repeater1.DataSource = SelctdRM;
repeater1.DataBind();
}
the problem is that every time I retreave the session to create a new list, the new data is added up to the old one. I want to have a situation where only the current data is displayed. I tried to clear the list, abandon the session, or clear the repeater before adding the new ones it did hehlp; easy there an easy way to get this done. many thanks
It sounds like you are calling SaveUserSelection multiple times from your javascript. If that's the case then only the very first time your list will be initialized.
Therefore, your list will keep adding stuff to the "old" list since the list has not been cleared or re-initialized .
You should probably put the initialization in a separate method (either on Page_Load or create a new WebMethod just to clear/initialized the list). For example, this is how it looks if you decide to put it on the Page_Load event:
Note: code no tested
private void Page_Load(object sender, System.EventArgs e)
{
if(!Page.IsPostBack)
Session["someinfo"] = new List<SelectRms>();
}
This is how it looks if you create a WebMethod:
[WebMethod(EnableSession = true)]
public void InitUserSelection()
{
Session["someinfo"] = new List<SelectRms>();
}
Call this method when you are ready to keep track of the user selection. Perhaps when your form initially loads (place this script at the bottom of the page):
$(document).ready(function() {
$.ajax({
type: "POST",
url: "PageName.aspx/InitUserSelection",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
// After init you could use this method to do something else
}
});
});
So SaveUserSelection will look like this:
[WebMethod(EnableSession = true)]
public void SaveUserSelection(string slctdRooms, string slctdcst)
{
List<SelectRms> SelectR = Session["someinfo"] as List<SelectRms>;
if (SelectR != null)
SelectR.Add(new SelectRms { roomtype = slctdRooms, Roomcst = slctdcst });
}
And this is how your javascript looks like whenever your selection changes:
$.ajax({
type: "POST",
url: "PageName.aspx/SaveUserSelection",
data: "{'slctdRooms':'Value1','slctdcst':'Value2'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
//your list was updated, you may do something afterwards
}
});
#Ulises. this is what I ma doing:
public List<SelectRms> GetUserContent()
{
List<SelectRms> SelectR=new List<SelectRms>();
Session["someinfo"] = SelectR;
return Session["someinfo"] as List<SelectRms>;
}
[WebMethod(EnableSession = true)]
public void SaveUserSelection(string slctdRooms, string slctdcst)
{
List<SelectRms> SelectR = GetUserContent();
SelectR.Add(new SelectRms { roomtype = slctdRooms, Roomcst = slctdcst });
}
But instead it returns a single (first) element of my list rather than the whole list, Any Help

Iterate through JSON object list provided by ASP.NET webservice

I have an ASP.NET webservice method that returns a generics list (List'<'Construct>) serialized as JSON, using code such as this:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class TestService : System.Web.Services.WebService {
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string GetOccupationListJSON(int SOCLevel)
{
Construct NewConstructList = new ConstructList();
DataContractJsonSerializer serializer = new DataContractJsonSerializer(ConstructList.GetType());
MemoryStream ms = new MemoryStream();
serializer.WriteObject(ms, NewConstructList);
string json = Encoding.Default.GetString(ms.ToArray());
return json;
}
}
I then use jQuery to call this method, and get the JSON data, like so:
function GetCustomerList() {
$.ajax({
type: "POST",
url: "/WebService.asmx/GetConstructList",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) { LoadConstructData(data.d); },
failure: function() { alert("Sorry, we were unable to find the constructs."); }
});
}
The JSON result looks like this:
[
{
"ConstructLabel": "Construct label 1",
"ConstructType": 2,
},
{
"ConstructLabel": "Construct label 2",
"ConstructType": 3,
}
]
I then want to iterate through the elements in the ConstructList in the JSON data. This is the function that gets called on when the jQuery Ajax call is successful:
function LoadConstructData(data) {
for (var i = 0, len = data.length; i < len; ++i) {
var Construct = data[i];
var ConstructLabel = Construct.ConstructLabel
var ConstructType = Construct.ConstructType;
}
}
I assumed (from looking elsewhere) that accessing the JSON data through the index would provide me with access to the underlying object at that index, so that I can then work with it to access its properties.
However, when i=0 and I do var Construct = data[i]; I get the character at the i position of the data array ([), and in the next iteration I get the second character ({). So clearly I am accessing the elements of a string array rather than the JSON data object.
How do I make sure that the data returned by the webservice gets into proper JSON format, so that I can iterate through the object elements within it?
You shouldn't manually serialize the JSON. The ScriptService will do that for you automatically if you define it like this:
[WebMethod]
public List<Construct> GetConstructList()
{
return new ConstructList();
}

ASP.NET: URI handling

I'm writing a method which, let's say, given 1 and hello should return http://something.com/?something=1&hello=en.
I could hack this together pretty easily, but what abstraction functionality does ASP.NET 3.5 provide for building URIs? I'd like something like:
URI uri = new URI("~/Hello.aspx"); // E.g. ResolveUrl is used here
uri.QueryString.Set("something", "1");
uri.QueryString.Set("hello", "en");
return uri.ToString(); // /Hello.aspx?something=1&hello=en
I found the Uri class which sounds highly relevant, but I can't find anything which does the above really. Any ideas?
(For what it's worth, the order of the parameters doesn't matter to me.)
Edited to correct massively incorrect code
Based on this answer to a similar question you could easily do something like:
UriBuilder ub = new UriBuilder();
// You might want to take more care here, and set the host, scheme and port too
ub.Path = ResolveUrl("~/hello.aspx"); // Assumes we're on a page or control.
// Using var gets around internal nature of HttpValueCollection
var coll = HttpUtility.ParseQueryString(string.Empty);
coll["something"] = "1";
coll["hello"] = "en";
ub.Query = coll.ToString();
return ub.ToString();
// This returned the following on the VS development server:
// http://localhost/Hello.aspx?something=1&hello=en
This will also urlencode the collection, so:
coll["Something"] = "1";
coll["hello"] = "en&that";
Will output:
Something=1&hello=en%26that
As far I know nothing here. So everybody has its own implementation.
Example from LinqToTwitter.
internal static string BuildQueryString(IEnumerable<KeyValuePair<string, string>> parameters)
{
if (parameters == null)
{
throw new ArgumentNullException("parameters");
}
StringBuilder builder = new StringBuilder();
foreach (var pair in parameters.Where(p => !string.IsNullOrEmpty(p.Value)))
{
if (builder.Length > 0)
{
builder.Append("&");
}
builder.Append(Uri.EscapeDataString(pair.Key));
builder.Append("=");
builder.Append(Uri.EscapeDataString(pair.Value));
}
return builder.ToString();
}
UPDATE:
You can also create extension method:
public static UriBuilder AddArgument(this UriBuilder builder, string key, string value)
{
#region Contract
Contract.Requires(builder != null);
Contract.Requires(key != null);
Contract.Requires(value != null);
#endregion
var query = builder.Query;
if (query.Length > 0)
{
query = query.Substring(1) + "&";
}
query += Uri.EscapeDataString(key) + "="
+ Uri.EscapeDataString(value);
builder.Query = query;
return builder;
}
And usage:
var b = new UriBuilder();
b.AddArgument("test", "test");
Please note that everything here is untested.
Just combined answers=>
public static class UriBuilderExtensions
{
public static void AddQueryArgument(this UriBuilder b, string key, string value)
{
key = Uri.EscapeDataString(key);
value = Uri.EscapeDataString(value);
var x = HttpUtility.ParseQueryString(b.Query);
if (x.AllKeys.Contains(key)) throw new ArgumentNullException
("Key '{0}' already exists!".FormatWith(key));
x.Add(key, value);
b.Query = x.ToString();
}
public static void EditQueryArgument(this UriBuilder b, string key, string value)
{
key = Uri.EscapeDataString(key);
value = Uri.EscapeDataString(value);
var x = HttpUtility.ParseQueryString(b.Query);
if (x.AllKeys.Contains(key))
x[key] = value;
else throw new ArgumentNullException
("Key '{0}' does not exists!".FormatWith(key));
b.Query = x.ToString();
}
public static void AddOrEditQueryArgument(this UriBuilder b, string key, string value)
{
key = Uri.EscapeDataString(key);
value = Uri.EscapeDataString(value);
var x = HttpUtility.ParseQueryString(b.Query);
if (x.AllKeys.Contains(key))
x[key] = value;
else
x.Add(key, value);
b.Query = x.ToString();
}
public static void DeleteQueryArgument(this UriBuilder b, string key)
{
key = Uri.EscapeDataString(key);
var x = HttpUtility.ParseQueryString(b.Query);
if (x.AllKeys.Contains(key))
x.Remove(key);
b.Query = x.ToString();
}
}
Half baked code. But should work well enough.
There's also the UriBuilder class
This is something that might appeal to you- recently at work I was looking at a way to "type" commonly used URL query string variables and so developed this interface:
'Represent a named parameter that is passed from page-to-page via a range of methods- query strings, HTTP contexts, cookies, session, etc.
Public Interface INamedParam
'A key that uniquely identfies this parameter in any HTTP value collection (query string, context, session, etc.)
ReadOnly Property Key() As String
'The default value of the paramter.
ReadOnly Property DefaultValue() As Object
End Interface
You can then implement this interface to describe a query string parameter, such an implementation for your "Hello" param might look like this:
Public Class HelloParam
Implements INamedParam
Public ReadOnly Property DefaultValue() As Object Implements INamedParam.DefaultValue
Get
Return "0"
End Get
End Property
Public ReadOnly Property Key() As String Implements INamedParam.Key
Get
Return "hello"
End Get
End Property
End Class
I developed a small (and very, very basic) class to help build URLs using these strongly typed parameters:
Public Class ParametrizedHttpUrlBuilder
Private _RelativePath As String
Private _QueryString As String
Sub New(ByVal relativePath As String)
_RelativePath = relativePath
_QueryString = ""
End Sub
Public Sub AddQueryParameterValue(ByVal param As INamedParam, ByVal value As Object)
Dim sb As New Text.StringBuilder(30)
If _QueryString.Length > 0 Then
sb.Append("&")
End If
sb.AppendFormat("{0}={1}", param.Key, value.ToString())
_QueryString &= sb.ToString()
End Sub
Public Property RelativePath() As String
Get
Return _RelativePath
End Get
Set(ByVal value As String)
If value Is Nothing Then
_RelativePath = ""
End If
_RelativePath = value
End Set
End Property
Public ReadOnly Property Query() As String
Get
Return _QueryString
End Get
End Property
Public ReadOnly Property PathAndQuery() As String
Get
Return _RelativePath & "?" & _QueryString
End Get
End Property
End Class
Here's my version (needs .NET4 or a ToArray() call on the Select)
var items = new Dictionary<string,string> { { "Name", "Will" }, { "Age", "99" }};
String query = String.Join("&", items.Select(i => String.Concat(i.Key, "=", i.Value)));
I thought the use of Dictionary might mean the items can get reordered, but that doesn't actually seem to be happening in experiments here - not sure what that's about.

DataTable to Json using jquery

I'm trying to execute a web service which returns a DataTable with the following piece of code:
$.ajax({
type: "POST",
url: url,
data: data,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
//do things
}
});
If the webservice returns a class then it works so it has nothing to do with the input paramters etc. It only fails when the web method returns a datatable (the datatable only has 2 columns and 2 rows for the test I'm doing).
The WebService class is decorated with the [ScriptService] attribute so I thought that ASP.NET would automatically serialize the return value as JSON. It doesn't seem to work with datatable.
The only solution I've found was to return a string (a manually JSON serialized object) but it doesn't seem right to me to do it this way.
I'm using Visual Studio 2008 with .Net 3.5
In the end, I've decided to use the JavaScriptSerializer class to convert the DataTable into a JSON string.
Unfortunately, this class doesn't work with a DataTable so I converted the DataTable into a list of dictionnaries and pass that list to the JavaScriptSerializer class. It takes only a few lines of code and it works fine.
Example in VB.net:
Public Function GetJson(ByVal dt As DataTable) As String
Dim serializer As System.Web.Script.Serialization.JavaScriptSerializer = New System.Web.Script.Serialization.JavaScriptSerializer()
Dim rows As New List(Of Dictionary(Of String, Object))
Dim row As Dictionary(Of String, Object)
For Each dr As DataRow In dt.Rows
row = New Dictionary(Of String, Object)
For Each col As DataColumn In dt.Columns
row.Add(col.ColumnName, dr(col))
Next
rows.Add(row)
Next
Return serializer.Serialize(rows)
End Function
Easiest way is to use the LINQ to DataSet extensions. First need to create a generic list (SearchSerialResults is just a DTO in this case) from the DataTable using LINQ to DataSet.
var resultItems = (from DataRow dr in _returnedData.AsEnumerable() select new SearchSerialResults {
ContractLineItem = (int) dr["fldContractLineItemID"],
SearchItem = (string) dr["Search Item"],
Customer = (string) dr["Customer"],
DeviceFound = (string) dr["Device Found"],
Country = (string) dr["Country"],
City = (string) dr["City"],
ContractNumber = (string) dr["Contract Number"],
QuoteNumber = (string) dr["Quote Number"],
BeginDate = (string) dr["Begin Date"],
EndDate = (string) dr["End Date"]
}).ToList();
_returnedData is the DataTable in this case. Step 2 is to do the conversion. In this case, I am returning a Json object for a jqGrid.
var jsonObject = new {
total = totalPages,
pageSize,
records = totalRecords,
rows = (from SearchSerialResults item in resultItems select new {
id = item.ContractLineItem,
cell = new [] {
item.ContractLineItem.ToString(),
item.SearchItem,
item.DeviceFound,
item.Customer,
item.ContractNumber,
item.QuoteNumber,
item.Country,
item.City,
item.BeginDate,
item.EndDate,
""
}
}).ToArray()
};
return Json(jsonObject) // for MVC
Json.NET has the ability to write DataSets/DataTables to JSON.
http://james.newtonking.com/archive/2008/09/06/dataset-datatable-serialization-with-json-net.aspx
http://schotime.net/blog/index.php/2008/07/27/dataset-datatable-to-json/
It works for very well for me with a WebService
Imports System.Web.Script.Serialization
Dim wsServicio As New ["YourWsInstance"]
Dim dsInstEstado As New DataSet
Dim sSql As String
sSql = " Your SQL Statement"
dsInstEstado = wsServicio.getData("YourWebServiceParameters")
Dim jsonString = DataTableToJSON(dsInstEstado.Tables("CA_INSTITUCION"))
Return Json(jsonString, JsonRequestBehavior.AllowGet)
Function DataTableToJSon(dt As DataTable) As Object
Dim arr(dt.Rows.Count - 1) As Object
Dim column As DataColumn
For i = 0 To dt.Rows.Count - 1
Dim dict As New Dictionary(Of String, Object)
For Each column In dt.Columns
dict.Add(column.ColumnName, dt.Rows(i)(column))
Next
arr(i) = dict
Next
Return arr
End Function
I must admit I'm not hugely surprised - DataTable basically breaks most of the rules of structured data. Why not simply project from the data-table into a typed object? A related question came up earlier... or if you know the schema of the DataTable just do the conversion in C#...
Manually building the JSON might work, but there are a lot of edge-cases to avoid; I'd rather let an existing framework handle it, to be honest.
.Net 3.5 has a JSONSerializer that should be able to handle a datatable. You may want to look at your service code again and try getting it to use that. Also, I put some code together to do it manually in this question.
Like Marc, I too am not surprised that the DataTable breaks your webservice/json exchange. I'd like to endorse Json.NET also.
But if you decide to not go with it, you still don't have to build the json manually. Just make your own lean custom class with all the properties you need and then return an array of that class. You will of course have to write code to "convert" your data table into your new class. I know, it could be a lot of code writing, but it's a lot less error prone then trying to manually make a json string.
I found this C# class very useful:
[Serializable]
public class TableMethod
{
private int m_total; public int total { get { return this.m_total; } set { this.m_total = value; } }
private int m_page; public int page { get { return this.m_page; } set { this.m_page = value; } }
private int m_records; public int records { get { return this.m_records; } set { this.m_records = value; } }
private IList<RowElement> m_rows; public IList<RowElement> rows { get { return this.m_rows; } set { this.m_rows = value; } }
public TableMethod()
{
this.m_records = 20;
this.m_total = 20;
this.m_page = 1;
}
}
[Serializable]
public class RowElement
{
public string id;
public string[] cell;
}

Resources