In my JSON file there is an array (rents). In this array there is a varible, serial, which can be null or a string. I loop throug my array (rents) if the serial variable is null i want to continue the loop, but when is it not null i want to save it. But somehow it does not behave like that. The array stop looping when it comes to get "serial".
Here is my code:
public static string sendRequest(string url, string method) {
try
{
// Set reqiued information for api
var httpWebRequest = (HttpWebRequest)WebRequest.Create(main_url + url);
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Headers.Add("Authorization", "Bearer " + Current_Access_Token);
httpWebRequest.Accept = "application/json;v=1";
httpWebRequest.Method = method;
// Get adn return responses
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
string respStr = new StreamReader(httpResponse.GetResponseStream()).ReadToEnd();
return respStr;
}
catch (Exception e)
{
MessageBox.Show("No responses");
}
return "";
}
public static void GetRentGames()
{
string resp = sendRequest("api.php/currentCustomer/rents", "GET");
JObject jObject = JObject.Parse(resp);
JArray Juser = (JArray)jObject["response"]["data"]["rents"];
//Console.WriteLine(resp);
foreach(var i in Juser)
{
var matchGame = ApiConnector.rentGame.Find(x => x.name == i["item"]["name"].ToString());
if(matchGame == null)
{
//name and id works just fine. it is the serial i can't get, and I think because the serial is null?
Console.WriteLine(i["serial"].ToString());
var Game = new RentGame(i["item"]["name"].ToString(), i["id"].ToString(), i["serial"].ToString());
rentGame.Add(Game);
Console.WriteLine("Add rent game " + Game.name);
}
}
}
JSON file- first index:
"response":{
"code":200,
"status":"success",
"data":{
"rents":[
{
"id":"34414",
"start_date":"2015-12-08",
"download_url":null,
"serial":null, ...
To determine if the value is null, do this:
if(matchGame == null)
{
// Only do this if the serial is not null
if (i["serial"].Type != JTokenType.Null)
{
Console.WriteLine(i["serial"].ToString());
var Game = new RentGame(i["item"]["name"].ToString(), i["id"].ToString(), i["serial"].ToString());
rentGame.Add(Game);
Console.WriteLine("Add rent game " + Game.name);
}
The difficulty is that the JSON parser does not convert null objects in JSON to null objects in C#. (why??!?) Instead, it makes it a JToken object, with a "Type" of "Null".
You can see this in the debugger window like this:
The "Value" column shows as {} which doesn't mean much to me. The "Type" column shows that it is a JToken object. So what is a JToken? Well, if you expand, you see it has lots of properties: Next, Last, Parent, Path, ... Okay, so that explains why they didn't make it a real null. They want to track all these other things. It looks like you could use the "HasValues" property or the "Type" property to see if the thing is null.
Well,
i["serial"].ToString()
will probably throw exception if i["serial"] == null.
The simplest solution would be to just check if it's not null and process it somehow afterwards.
Related
I have the following function that allows me to make REST request via this function:
static Observation GetData(string baseUrl, string provider, string key, string sensor)
{
var client = new RestClient(String.Format("{0}/data/{1}/{2}", baseUrl, provider, sensor));
client.Timeout = -1;
var request = new RestRequest(Method.GET);
request.AddHeader("IDENTITY_KEY", key);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
var observationsModel = JsonSerializer.Deserialize<SentiloResponse>(response.Content, options);
Console.WriteLine("This is observationsModel:");
Console.WriteLine(observationsModel);
Console.WriteLine("This is the outcome of GetData:");
Console.WriteLine(observationsModel.Observations.FirstOrDefault());
return observationsModel.Observations.FirstOrDefault();
}
The outcome from it is the following (see screenshot):
Now, from this point
In the next section I call GetData, I would like to select Value and Timestamp Variables to do other tasks, but I'm unable to (my attempts are in lines where myTest and myTest_2 are being declared):
static void Main(string[] args)
{
configuration = JsonSerializer.Deserialize<SentiloConfig>(File.ReadAllText("configuration.json"), options);
Console.WriteLine("Configuration Loaded");
foreach(var componentMapping in configuration.ComponentMappings)
{
var inputComponent = componentMapping.InputComponent;
Console.WriteLine("Getting data");
var sensorsContent = inputComponent.Sensors.AsParallel().Select(s =>
new SensorContent{
Sensor = GetSensorString(s.SensorName),
Observations = new List<Observation>() {
GetData(
inputComponent.ServerUrl,
inputComponent.Provider,
inputComponent.Token,
GetSensorString(s.SensorName)
)
}
}
).Where(s => s.Observations.First() != null).ToList();
var myTest = sensorsContent.Select(s => s.Observations.First().Value).ToList();
var myTest_2 = sensorsContent.Select(s => s.Observations.First().Value.ToList());
Console.WriteLine(myTest.ToString());
Console.WriteLine(myTest_2);
Console.WriteLine("data retrieved");
if (!sensorsContent.Any())
{
Console.WriteLine("No sensor data for component {0} with sensors: {1}, check configuration", inputComponent.ComponentName, string.Join(",", inputComponent.Sensors.Select(s => s.SensorName)));
continue;
}
var sensorRequest = new SentiloPutRequest { Sensors = sensorsContent };
}
System.Threading.Thread.Sleep(configuration.SendTime*1000);
}
But the outcome of myTest and myTest_2 are the following:
System.Collections.Generic.List1[System.String] System.Linq.Enumerable+SelectListIterator2[SentiloSpoofer.SensorContent,System.Collections.Generic.List`1[System.Char]]
I'm thinking perhaps is best to call GetData outside of the Lambda and bypass these issues, but if I wanted to retrieve this data, what could be a good way to do so?
It's just the way you are writing to the console. Use string.Join or a foreach.
Essentially, you are trying to magic the values out of a list. Technically List<T> doesn't have an override of ToString() that knows how you want to format it. It's up to you. So it just returns the type name (which is what you are seeing).
Try instead:
foreach(var value in myTest)
Console.WriteLine(value);
// or
Console.WriteLine(string.Join(",",myTest));
You are trying to access a List as a String.
The values are there if you wanna show it in your console, just use an aggregate in your List.
Example:
var myTestString = myTest.Select(i => i).Aggregate((i, j) => i + "," + j);
Console.WriteLine(myTestString)
// Or
myTest.ForEach(x => Console.WriteLine(x));
I saw plenty of similar questions but I really could not work my way around this time. What I am having issues with, is populating a view with the content of a certain object in order to update it. When I press on "Edit", in theory, all the fields should be automatically inserted. What have I tried so far?
public ActionResult CreateOrEdit(int id = 0)
{
if (id==0)
return View(new Recipe());
else
{
HttpResponseMessage response = GlobalVariables.client.GetAsync(id.ToString()).Result;
//return ViewJsonConvert.DeserializeObject<IList<Recipe>>(response.ToString()));
return View(response.Content.ReadAsAsync<Recipe>().Result);
//return View(new Recipe());
}
}
return View(response.Content.ReadAsAsync<Recipe>().Result); - when using this as a return, I am getting this error:
Cannot deserialize the current JSON array (e.g. [1,2,3])
After looking the problem up, I tried the following:
return View(JsonConvert.DeserializeObject<IList<Recipe>>(response.ToString())); which got me this error:
{"Unexpected character encountered while parsing value: s. Path '', line 0, position 0."}
And at this point I am stuck. I would assume that it is trying to deserialize the following JSON:
{
"id": 5002,
"name": "Test Recipe",
"recipeLink": "testlink",
"category1Id": 7757,
"category2Id": 7758,
"category3Id": 7759,
"category4Id": 7760,
"recipeById": 1,
"totalTime": 30,
"totalTimeUnitId": 1,
"activeTime": 20,
"activeTimeUnitId": 1,
"instructions": "Test Instructions",
"sourceKey": "Test SK",
"recipeBy": "TestPerson",
"insertedAtUtc": "2019-09-04T12:18:48.0466667",
"isVerified": 1,
"numPersons": 5
}
If needed, here is the code from the API Controller that is handling the operations.
[Route("v1/recipe/{id}")]
[HttpPut()]
public IActionResult UpdateList(int id, [FromBody]Recipe recipe)
{
var category1Id = 7757;
var category2Id = 7758;
var category3Id = 7759;
var category4Id = 7760;
var isVerified = 0;
var recipeBy = "TestPerson";
var recipeById = 1;
try
{
if (recipe == null) throw new ArgumentException("No data specified");
//if (newData.Name == null) throw new ArgumentException("No name specified");
using (var con = _connFactory())
{
con.Execute(#"UPDATE dbo.Recipe SET Name=#name, RecipeLink=#recipeLink, Category1Id=#category1Id ,Category2Id=#category2Id,
Category3Id=#category3Id, Category4Id=#category4Id, RecipeById=#recipeById, TotalTime=#totalTime, TotalTimeUnitId=#totalTimeUnitId,
ActiveTime=#activeTime, ActiveTimeUnitId=#activeTimeUnitId, Instructions=#instructions, SourceKey=#sourceKey, RecipeBy=#recipeBy,
InsertedAtUtc=getutcdate(), IsVerified=#isVerified, NumPersons=#numPersons WHERE Id=#id",
new
{
id,
recipe.name,
recipe.recipeLink,
category1Id,
category2Id,
category3Id,
category4Id,
recipeById,
recipe.totalTime,
recipe.totalTimeUnitId,
recipe.activeTime,
recipe.activeTimeUnitId,
recipe.instructions,
recipe.sourceKey,
recipeBy,
isVerified,
recipe.numPersons
});
}
return Ok(recipe);
}
catch (Exception exc)
{
return BadRequest();
}
}
I believe your response string starts with the Unicode Byte Order Mark character.
For example...
using Newtonsoft.Json;
namespace StackOverflow
{
class MainClass
{
public static void Main(string[] args)
{
var json = #"{
'id': 5002,
'name': 'Test Recipe',
'recipeLink': 'testlink',
'category1Id': 7757,
'category2Id': 7758,
'category3Id': 7759,
'category4Id': 7760,
'recipeById': 1,
'totalTime': 30,
'totalTimeUnitId': 1,
'activeTime': 20,
'activeTimeUnitId': 1,
'instructions': 'Test Instructions',
'sourceKey': 'Test SK',
'recipeBy': 'TestPerson',
'insertedAtUtc': '2019-09-04T12:18:48.0466667',
'isVerified': 1,
'numPersons': 5
}".Replace("'", "\"");
//This works...
var deserialized1 = JsonConvert.DeserializeObject(json);
//Prepend a U+FEFF Byte Order Mark character...
json = "\uFEFF" + json;
//This fails with error:
//Newtonsoft.Json.JsonReaderException:
//Unexpected character encountered while parsing value: . Path '', line 0, position 0.
var deserialized2 = JsonConvert.DeserializeObject(json);
}
}
}
I wonder if you have a string value where it is expecting an integer, i.e. a character which is not wrapped in quotation marks.
Could you debug to the line JsonConvert.DeserializeObject<IList<Recipe>>(response.ToString())); in Visual Studio and then inspect the contents of "response" in the locals window and post a screenshot to help diagnose the issue?
Edit in response to comment:
Try adding these steps in before the return, then see what is contained in the temp variable:
string temp = response.Content.ReadAsAsync<string>().Result;
It will be interesting to see what this holds, maybe then it will show why the data cannot be parsed into a Recipe object.
Further edit
OK, instead of that line that won't execute try adding this code:
Stream receiveStream = response.GetResponseStream();
StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
var temporaryData = readStream.ReadToEnd();
See if that will execute and then inspect the contents of tempoararyData variable.
Edit 3
OK great we can see the data now. I believe the issue is it is coming through as a JSON array and you're trying to deserialize a singular version. I made this demo app to illustrate:
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
string data = "[{\"Id\":5002,\"Name\":\"Test Recipe\"}]";
string data2 = "{\"Id\":5002,\"Name\":\"Test Recipe\"}";
//This throws an exception
//DataClass account = JsonConvert.DeserializeObject<DataClass>(data);
//This works
DataClass account2 = JsonConvert.DeserializeObject<DataClass>(data2);
//This also works
DataClass[] account3 = JsonConvert.DeserializeObject<DataClass[]>(data);
}
}
class DataClass
{
public int Id { get; set; }
public string Name { get; set; }
}
}
I believe if you change your code to deserialize an array i.e. DeserializeObject<IList<Recipe[]>> hopefully it will work
I'm looking to see if there is a way to eliminate one of the two calls that gets made to my method to google maps to calculate long/lat coordinates.
Here is my method.
public static GeocoderCoordinates GetCoordinates(string region)
{
WebRequest request = WebRequest.Create("http://maps.googleapis.com/maps/api/geocode/xml?sensor=false&address=" + HttpUtility.UrlEncode(region));
using (WebResponse response = request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
XDocument document = XDocument.Load(new StreamReader(stream));
XElement longitudeElement = document.Descendants("lng").FirstOrDefault();
XElement latitudeElement = document.Descendants("lat").FirstOrDefault();
if (longitudeElement != null && latitudeElement != null)
{
return new GeocoderCoordinates
{
Longitude = Double.Parse(longitudeElement.Value, CultureInfo.InvariantCulture),
Latitude = Double.Parse(latitudeElement.Value, CultureInfo.InvariantCulture)
};
}
}
}
return null;
}
The first time I call this method it's for validation.
internal class ValidateLocationAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
var location = value as string;
GeocoderCoordinates coordinates = Geocoding.GetCoordinates(location);
if (coordinates == null)
return false;
return true;
}
}
and if there is no location that gets found it returns null - validation fails.
The second time it gets called is in the controller to set longitude/latitude coordinates within my entity.
[HttpPost]
public ActionResult Edit(EditStudentViewModel viewModel)
{
if (ModelState.IsValid)
{
Student student = studentRepository.Find(User.Identity.GetUserId());
if (student == null)
{
var newStudent = new Student
{
AspNetUserRefId = viewModel.AspNetUserRefId,
CatchPhrase = viewModel.CatchPhrase,
StartedPracticing = Convert.ToInt16(viewModel.SelectedYearId),
LocationPoints = Geocoding.GetDbGeography(viewModel.Location),
Location = viewModel.Location,
SO I'm running through this method twice just to insert/update a student. It seems a little redundant.
Isn't there a way to trigger/set validation state while the code in the controller is running, so I don't have to call this method twice (once for validation and once to set the actual values) when the user submits the form?
I thought about caching but don't think it's a good idea, unless someone can point out something.
If you think applying validation upfront using an attribute on the text box serve value to the user (early feedback), keep things as it is. Two calls is not too bad at all considering the value and cleanliness of the solution.
Second option is you can remove the attribute, and perform the validation in the controller action. If validation fails, display same form with all the same data but error message for the text box value (location). User will need to choose another location and then submit.
It is a trade off.
Important Tip: You can optimize your solution by storing region names in your DB and going to google API only if the region name does not present in your DB.
Question Background:
Update:
I'm still not sure how to go about extracting the relevant information from this response. I have tried setting my response type to JSON but still receive the response as shown below. I have taken into account what has been said in regards to using NameValueCollection but still cant see how this will help with such a large response. Ideally I'd like this mapped to an object structure of some kind, it dosen't necessarily have to be JSON.
Question:
I'm currently using the PayPal Api 'ExpressCheckout' method to allow users to pay for items on my test site. A HTTP response from the API provides a large response containing key information I need to extract - such as the buyers address, if the payment was succesful etc.
The Issue:
Currently I'm stuck on how to work with the response. Ideally I'd convert the data to a JSON string then use Newtonsoft to map the data to C# classes thus allowing easy access to the data. Here is an example of the Httpresponse:
TOKEN=EC%2XXXXXXXXXXXXXXXXXR&BILLINGAGREEMENTACCEPTEDSTATUS=0&CHECKOUTSTATUS=PaymentActionNotInitiated&TIMESTAMP=2015%2d01%2d02T21%3a11%3a30Z&CORRELATIONID=ab184fdba7a30&ACK=Success&VERSION=88%2e0&BUILD=14443165&EMAIL=test%40aol%2ecom&PAYERID=3XXXXXXXXXX4N&PAYERSTATUS=verified&BUSINESS=Test%20Biz%27s%20Test%20Store&FIRSTNAME=Joe&LASTNAME=King&COUNTRYCODE=GB&SHIPTONAME=Joe%20King%27s%20Test%20Store&SHIPTOSTREET=1%20Main%20Terrace&SHIPTOCITY=Wolverhampton&SHIPTOSTATE=West%20Midlands&SHIPTOZIP=W12%204LQ&SHIPTOCOUNTRYCODE=GB&SHIPTOCOUNTRYNAME=United%20Kingdom&ADDRESSSTATUS=Confirmed&CURRENCYCODE=GBP&AMT=15%2e56&ITEMAMT=15%2e56&SHIPPINGAMT=0%2e00&HANDLINGAMT=0%2e00&TAXAMT=0%2e00&INSURANCEAMT=0%2e00&SHIPDISCAMT=0%2e00&L_NAME0=ItemOne&L_QTY0=4&L_TAXAMT0=0%2e00&L_AMT0=3%2e89&L_ITEMWEIGHTVALUE0=%20%20%200%2e00000&L_ITEMLENGTHVALUE0=%20%20%200%2e00000&L_ITEMWIDTHVALUE0=%20%20%200%2e00000&L_ITEMHEIGHTVALUE0=%20%20%200%2e00000&PAYMENTREQUEST_0_CURRENCYCODE=GBP&PAYMENTREQUEST_0_AMT=15%2e56&PAYMENTREQUEST_0_ITEMAMT=15%2e56&PAYMENTREQUEST_0_SHIPPINGAMT=0%2e00&PAYMENTREQUEST_0_HANDLINGAMT=0%2e00&PAYMENTREQUEST_0_TAXAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEAMT=0%2e00&PAYMENTREQUEST_0_SHIPDISCAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false&PAYMENTREQUEST_0_SHIPTONAME=Joe%20King%27s%20Test%20Store&PAYMENTREQUEST_0_SHIPTOSTREET=1%20Main%20Terrace&PAYMENTREQUEST_0_SHIPTOCITY=Wolverhampton&PAYMENTREQUEST_0_SHIPTOSTATE=West%20Midlands&PAYMENTREQUEST_0_SHIPTOZIP=W12%204LQ&PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE=GB&PAYMENTREQUEST_0_SHIPTOCOUNTRYNAME=United%20Kingdom&PAYMENTREQUEST_0_ADDRESSSTATUS=Confirmed&L_PAYMENTREQUEST_0_NAME0=ItemOne&L_PAYMENTREQUEST_0_QTY0=4&L_PAYMENTREQUEST_0_TAXAMT0=0%2e00&L_PAYMENTREQUEST_0_AMT0=3%2e89&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE0=%20%20%200%2e00000&PAYMENTREQUESTINFO_0_ERRORCODE=0
If anyone could give me an easy way to map this data to a C# object that would be great.
Is there any specific reason why you want it in JSON format? If its not requirement and if you can live with key value pair then here is one way you can process response as key value pair.
public partial class Form1 : Form
{
Dictionary<string, string> processedResponse = null;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string rawResponse = "TOKEN=EC%2XXXXXXXXXXXXXXXXXR&BILLINGAGREEMENTACCEPTEDSTATUS=0&CHECKOUTSTATUS=PaymentActionNotInitiated&TIMESTAMP=2015%2d01%2d02T21%3a11%3a30Z&CORRELATIONID=ab184fdba7a30&ACK=Success&VERSION=88%2e0&BUILD=14443165&EMAIL=test%40aol%2ecom&PAYERID=3XXXXXXXXXX4N&PAYERSTATUS=verified&BUSINESS=Test%20Biz%27s%20Test%20Store&FIRSTNAME=Joe&LASTNAME=King&COUNTRYCODE=GB&SHIPTONAME=Joe%20King%27s%20Test%20Store&SHIPTOSTREET=1%20Main%20Terrace&SHIPTOCITY=Wolverhampton&SHIPTOSTATE=West%20Midlands&SHIPTOZIP=W12%204LQ&SHIPTOCOUNTRYCODE=GB&SHIPTOCOUNTRYNAME=United%20Kingdom&ADDRESSSTATUS=Confirmed&CURRENCYCODE=GBP&AMT=15%2e56&ITEMAMT=15%2e56&SHIPPINGAMT=0%2e00&HANDLINGAMT=0%2e00&TAXAMT=0%2e00&INSURANCEAMT=0%2e00&SHIPDISCAMT=0%2e00&L_NAME0=ItemOne&L_QTY0=4&L_TAXAMT0=0%2e00&L_AMT0=3%2e89&L_ITEMWEIGHTVALUE0=%20%20%200%2e00000&L_ITEMLENGTHVALUE0=%20%20%200%2e00000&L_ITEMWIDTHVALUE0=%20%20%200%2e00000&L_ITEMHEIGHTVALUE0=%20%20%200%2e00000&PAYMENTREQUEST_0_CURRENCYCODE=GBP&PAYMENTREQUEST_0_AMT=15%2e56&PAYMENTREQUEST_0_ITEMAMT=15%2e56&PAYMENTREQUEST_0_SHIPPINGAMT=0%2e00&PAYMENTREQUEST_0_HANDLINGAMT=0%2e00&PAYMENTREQUEST_0_TAXAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEAMT=0%2e00&PAYMENTREQUEST_0_SHIPDISCAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false&PAYMENTREQUEST_0_SHIPTONAME=Joe%20King%27s%20Test%20Store&PAYMENTREQUEST_0_SHIPTOSTREET=1%20Main%20Terrace&PAYMENTREQUEST_0_SHIPTOCITY=Wolverhampton&PAYMENTREQUEST_0_SHIPTOSTATE=West%20Midlands&PAYMENTREQUEST_0_SHIPTOZIP=W12%204LQ&PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE=GB&PAYMENTREQUEST_0_SHIPTOCOUNTRYNAME=United%20Kingdom&PAYMENTREQUEST_0_ADDRESSSTATUS=Confirmed&L_PAYMENTREQUEST_0_NAME0=ItemOne&L_PAYMENTREQUEST_0_QTY0=4&L_PAYMENTREQUEST_0_TAXAMT0=0%2e00&L_PAYMENTREQUEST_0_AMT0=3%2e89&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE0=%20%20%200%2e00000&PAYMENTREQUESTINFO_0_ERRORCODE=0";
//Process response
processedResponse = ProcessResponse(rawResponse);
//Use received data e.g.
//Get First name
string fName = GetRecordValue("FIRSTNAME");
//Get Last name
string lName = GetRecordValue("LASTNAME");
}
private Dictionary<string,string> ProcessResponse(string response)
{
Dictionary<string, string> responseData = new Dictionary<string, string>();
if(!string.IsNullOrWhiteSpace(response))
{
string[] firstPass = response.Split(new char[] { '&' });
foreach(string pair in firstPass)
{
string[] secondPass = pair.Split(new char[] { '=' });
if(secondPass!=null && secondPass.Length>0)
{
responseData.Add(secondPass[0].Trim(), secondPass[1].Trim());
}
}
}
return responseData;
}
private string GetRecordValue(string record)
{
string recordValue = null;
if(processedResponse!=null)
{
if(!string.IsNullOrWhiteSpace(record) && processedResponse.ContainsKey(record))
{
recordValue= processedResponse[record];
}
}
return recordValue;
}
}
Still unsure what's the problem with dealing with it as a NameValueCollection.
E.g.
//NameValueCollection
//or use HttpUtility.ParseQueryString(some_string_of_names_values)
var foo = Request.QueryString;
var bar = foo["FIRSTNAME"]; //based on above this is "Joe"
Update:
It is response string which is being processed here and not request hence you wont be able to retrieve details using Request.QueryString
As stated in comments:
string rawResponse = "TOKEN=EC%2XXXXXXXXXXXXXXXXXR&BILLINGAGREEMENTACCEPTEDSTATUS=0&CHECKOUTSTATUS=PaymentActionNotInitiated&TIMESTAMP=2015%2d01%2d02T21%3a11%3a30Z&CORRELATIONID=ab184fdba7a30&ACK=Success&VERSION=88...."
var foo = HttpUtility.ParseQueryString(rawResponse); //NameValueCollection
var bar = foo["FIRSTNAME"]; //Joe
I have following method:
public static string GetHttpHost(System.Web.HttpRequest hr)
{
return "http://" + hr.Url.Host + ":" + hr.Url.Port.ToString() ;
}
When I call this method with GetHttpHost(this.Request) and GetHttpHost(HttpContext.Current.Request), it returns different results.
For example:
My request page is http://192.168.1.103/mypage.aspx
In mypage.aspx.cs, calling GetHttpHost(this.Request) returns http://192.168.1.103:80
When rendering mypage.aspx, some biz logic is involved, so BLL.dll is loaded. In BLL.dll, calling GetHttpHost(HttpContext.Current.Request) returns http://app133:80 (app133 is our web server's name)
I searched in Stack Overflow, all related questions tell me that HttpContext.Current.Request and Page.Request are same object.
So, can anyone tell me what happened in my code?
Thanks.
No, HttpContext.Current.Request and Page.Request are not the same. Both are instances of the same class (HttpRequest) but those are different instances.
In each case, the private HttpRequest instance is created differently - I could not find the exact code creating it but keep in mind that HttpContext.Current is created only once, long before any Page.
It all boils down to the following code in HttpRequest class:
public Uri Url
{
get
{
if (this._url == null && this._wr != null)
{
string text = this.QueryStringText;
if (!string.IsNullOrEmpty(text))
{
text = "?" + HttpUtility.CollapsePercentUFromStringInternal(text, this.QueryStringEncoding);
}
if (AppSettings.UseHostHeaderForRequestUrl)
{
string knownRequestHeader = this._wr.GetKnownRequestHeader(28);
try
{
if (!string.IsNullOrEmpty(knownRequestHeader))
{
this._url = new Uri(string.Concat(new string[]
{
this._wr.GetProtocol(),
"://",
knownRequestHeader,
this.Path,
text
}));
}
}
catch (UriFormatException)
{
}
}
if (this._url == null)
{
string text2 = this._wr.GetServerName();
if (text2.IndexOf(':') >= 0 && text2[0] != '[')
{
text2 = "[" + text2 + "]";
}
this._url = new Uri(string.Concat(new string[]
{
this._wr.GetProtocol(),
"://",
text2,
":",
this._wr.GetLocalPortAsString(),
this.Path,
text
}));
}
}
return this._url;
}
}
As you can see, it first tries to read known request header (GetKnownRequestHeader method in System.Web.HttpWorkerRequest base class) and only if it fails it will invoke GetServerName method which will return either IP address or server name depending where the web application is hosted.
Didn't find any official documentation or proof as to why exactly one returns IP and other the machine name, but the above can explain the difference.