How to convert an entity?

raysefo

Well-known member
Joined
Feb 22, 2019
Messages
155
Programming Experience
10+
Hi,

I would like to know if I can convert my entity into this format?

C#:
version=V1&signature=5e7efbcf0c9cb2211&ApplicationCode=52e7cf966b724749a
Thanks in advance.
 

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
365
Location
Virginia Beach, VA
Programming Experience
10+
You could, but why would you?

Normally most people avoid passing parameters as URLs nowadays because of:
- possibility of URL hacking -- somebody can start calling your WebAPI with invalid data in the query string that you weren't expecting
- potential exposure of sensitive information
- hitting URL length limits with different browsers -- yes, there's an RFC but not everybody follows it
- inconsistent URL encoding/decoding performed by browsers, proxies, and etc. -- yes there's an RFC but not everybody follows it

Anyway if you are only concerned with your specific class is fixed, then building up that query string is a simple concatenation exercise. If you need something generic, see some of the approaches on StackOverflow. All of them basically enumerate the properties of a class and start building a string based on the property names and values.
 

raysefo

Well-known member
Joined
Feb 22, 2019
Messages
155
Programming Experience
10+
I am trying to generate a request, that's why I needed @Skydiver

C#:
//HTTPWebRequest
var request = (HttpWebRequest) WebRequest.Create("http://test/pinstore/" + url);
request.ContentType = "application/json";
request.Method = "POST";

//Generate Request
string requestString =
                      $"version={productRequest.version}&signature={productRequest.signature}&ApplicationCode={productRequest.ApplicationCode}";

using (var streamWriter = new StreamWriter(await request.GetRequestStreamAsync()))
{
     streamWriter.Write(requestString);
}

HttpWebResponse httpResponse = (HttpWebResponse) (await request.GetResponseAsync());
string json;
using (Stream responseStream = httpResponse.GetResponseStream())
{
     json = new StreamReader(responseStream).ReadToEnd();
}

response = new HttpResponseMessage
{
        StatusCode = System.Net.HttpStatusCode.OK,
        Content = new StringContent(json, System.Text.Encoding.UTF8, "application/json"),
};
                        
                  
return response;
 

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
365
Location
Virginia Beach, VA
Programming Experience
10+
Hmmm... if the content type for your request is JSON, why are you sending web forms content?
 

Sheepings

Senior Programmer
Joined
Sep 5, 2018
Messages
345
Location
UK
Programming Experience
10+
I would like to know if I can convert my entity into this format?
Not directly no. Kinda defeats the purpose of using a DB mapper. No?
I hope you're planning on encoding them urls. Edit, at a second glance, it doesn't look like gamesultan care about decoding if you're not encoding them. What protection do they have to prevent URI hijacking. . .

They should consider some encryption if you ask me. But they're not asking me so who cares i guess.
 
Last edited:

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
365
Location
Virginia Beach, VA
Programming Experience
10+
On viewing his code, he doesn't have to worry about the URL hacking and hijacking issues because he is not appending the string as a query string for the URL. Instead he is sending the string as the payload of his HTTP POST.

Personally, follow the KISS and YAGNI principles. If your payload only consists of those 3 fields, or a very limited set of fields across two different classes, then just use the code you have. No need to implement a generic solution that does reflection.

As noted above, you may need to worry about URL encoding, but really depends on what type of payload that game API is expecting.
 

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
365
Location
Virginia Beach, VA
Programming Experience
10+
If you are going async for getting the request stream, why are you also going async for getting the response stream? Is it because you believe that the entire response is small enough to come as a single packet when you got the response asynchronously?

Anyway, async here is orthogonal to the main topic of this thread: building up the payload string for your web request to the game web API that you are using.
 

raysefo

Well-known member
Joined
Feb 22, 2019
Messages
155
Programming Experience
10+
Here is good news for you @Skydiver and @Sheepings :) I tried load test with 2100 users and there is no error. Thank you for all the support and sorry for the troubles I made. One last question I hope, the response may not be small so should I remove await from response?

Here is the code sample:
C#:
//HTTPWebRequest
var request = (HttpWebRequest) WebRequest.Create("http://qa-api.mol.com/pinstore/" + url);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";

var keyValueContent = productRequest.ToKeyValue();
var formUrlEncodedContent = new FormUrlEncodedContent(keyValueContent);
var urlEncodedString = await formUrlEncodedContent.ReadAsStringAsync();

using (var streamWriter = new StreamWriter(await request.GetRequestStreamAsync()))
{
      streamWriter.Write(urlEncodedString);
}

HttpWebResponse httpResponse = (HttpWebResponse) (await request.GetResponseAsync());
string json;
using (Stream responseStream = httpResponse.GetResponseStream())
{
      json = new StreamReader(responseStream).ReadToEnd();
}
                    
            
return response;
Here is the ToKeyValues:

C#:
public static IDictionary<string, string> ToKeyValues(this object metaToken)

{

     if (metaToken == null)

     {

         return null;

     }


     JToken token = metaToken as JToken;

     if (token == null)

     {

         return ToKeyValues(JObject.FromObject(metaToken));

     }


     if (token.HasValues)

     {

         var contentData = new Dictionary<string, string>();


         foreach (var child in token.Children().ToList())

         {

              var childContent = child.ToKeyValues();

              if (childContent != null)

              {

                    contentData = contentData.Concat(childContent).ToDictionary(k => k.Key, v => v.Value);

              }

         }


         return contentData;

}


var jValue = token as JValue;

if (jValue?.Value == null)

{

     return null;

}


var value = jValue?.Type == JTokenType.Date

         ? jValue?.ToString("o", CultureInfo.InvariantCulture)

         : jValue?.ToString(CultureInfo.InvariantCulture);


return new Dictionary<string, string> {{token.Path, value}};

}
 

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
365
Location
Virginia Beach, VA
Programming Experience
10+
Since you are returning response on line 23, and not really doing anything with the HttpWebResponse because you just throw away the json string, you might as well just delete lines 15-22.
 

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
365
Location
Virginia Beach, VA
Programming Experience
10+
Also as an aside, why do you need lines 8-12? Why not just use CopyToAsync() ?
 

raysefo

Well-known member
Joined
Feb 22, 2019
Messages
155
Programming Experience
10+
I somehow added missing code, here is the full code:
C#:
//HTTPWebRequest
var request = (HttpWebRequest)WebRequest.Create("http://qa-api.mol.com/pinstore/" + url);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";

var keyValueContent = gameRequest.ToKeyValue();
var formUrlEncodedContent = new FormUrlEncodedContent(keyValueContent);
var urlEncodedString = await formUrlEncodedContent.ReadAsStringAsync();

using (var streamWriter = new StreamWriter(await request.GetRequestStreamAsync()))
{
      streamWriter.Write(urlEncodedString);
}

HttpWebResponse httpResponse = (HttpWebResponse)(await request.GetResponseAsync());
string json;
using (Stream responseStream = httpResponse.GetResponseStream())
{
      json = new StreamReader(responseStream).ReadToEnd();
}

response = new HttpResponseMessage
{
      StatusCode = System.Net.HttpStatusCode.OK,
      Content = new StringContent(json, System.Text.Encoding.UTF8, "application/json"),
};



return response;
 

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
365
Location
Virginia Beach, VA
Programming Experience
10+
Why not just use StreamContent on line 25? Just pass in the httpResponse.GetResponseStream(), so that you can get rid of lines 16-20.

Why not just use CopyToAsync() to replace lines 8-13?
 

raysefo

Well-known member
Joined
Feb 22, 2019
Messages
155
Programming Experience
10+
@Skydiver I don't understand how to use copytoasync?

C#:
//HTTPWebRequest
var request = (HttpWebRequest) WebRequest.Create("http://qa-api.mol.com/pinstore/" + url);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";

var keyValueContent = productRequest.ToKeyValue();
var formUrlEncodedContent = new FormUrlEncodedContent(keyValueContent);
var urlEncodedString = await formUrlEncodedContent.ReadAsStringAsync();
using (var streamWriter = new StreamWriter(await request.GetRequestStreamAsync()))
{
     streamWriter.Write(urlEncodedString);
}

HttpWebResponse httpResponse = (HttpWebResponse) (await request.GetResponseAsync());
                
response = new HttpResponseMessage
{
     StatusCode = httpResponse.StatusCode,
     Content = new StreamContent(httpResponse.GetResponseStream()),
};
                        
return response;
 

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
365
Location
Virginia Beach, VA
Programming Experience
10+
Do you even understand what your lines 8-12 are currently doing? Or did you just copy and paste it from someplace else? All it is doing is copying the contents into the stream. Sounds like a perfect match for a function that is actually named aptly so.
 

Sheepings

Senior Programmer
Joined
Sep 5, 2018
Messages
345
Location
UK
Programming Experience
10+
@Skydiver I don't understand how to use copytoasync?
How come? The docs are insightful.
Do you even understand what your lines 8-12 are currently doing?
Once again, ignoring important questions? If you don't know what your own code is doing, how do you expect it to work correctly?
 
Top Bottom