How to convert response of post request to bool in C# - c#

I have an endpoint with functionname (( CallTrafficEndPoint )) this request was developed by RestSharp Methdology
And I call this endpoint from other place in code but the retrieved type was (RequestData)
so How can I retrive a bool value from this request?
namespace Business.TrafficIntegration
{
public static class Calling_API
{
public static RequestData CallTrafficEndPoint(RequestData TrafficModel, CrmDAL crmDal)
{
RequestData IsLicenseValid;
Utility.Utility utility = new Utility.Utility(crmDal);
string serviceURL = utility.GetAdminConfigurationValue("valid-licence");
var client = new RestClient(serviceURL);
var request = new RestRequest();
var body = new RequestData();
body = TrafficModel;
request.AddJsonBody(body);
using (MemoryStream DeSerializememoryStream = new MemoryStream())
{
//Json String that we get from web api
var response = client.Post(request);
//initialize DataContractJsonSerializer object and pass Student class type to it
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(RequestData));
//user stream writer to write JSON string data to memory stream
StreamWriter writer = new StreamWriter(DeSerializememoryStream);
writer.Write(response);
writer.Flush();
DeSerializememoryStream.Position = 0;
//get the Desrialized data
RequestData SerializedObject = (RequestData)serializer.ReadObject(DeSerializememoryStream);
IsLicenseValid = SerializedObject;
// throw new InvalidPluginExecutionException("The retrieved value " + IsLicenseValid);
return IsLicenseValid;
}
}
}
}

Related

How to write Testcases for an API that accepts an object that includes IFormFile typed fields in .NET

This is my controller code. Here it accepts UpdateMediaDto object that contains IFormFile data ( e.g. images and audios).
[HttpPut("words/{wordId}/medias/{id}")]
public async Task<ActionResult<WordMediaDto>> UpdateWordMedia(Guid wordId, Guid id, [FromForm] UpdateMediaDto mediaDto)
{
WordMedia? media = await _unitOfWork.WordMediaRepository.GetByIdAsync(id);
if (media == null) return NotFound();
if (wordId != media.WordId) return BadRequest("No Word present for this media");
var newMedia = _mediaFileMasterService.UpdateMedias(mediaDto);
//............
}
And this is my testcase
[Fact]
public async Task PUT_Media_with_UpdateMediaDto_results_WordMediaDto_success()
{
var ImagefileMock = new Mock<IFormFile>();
var content = System.Text.Encoding.UTF8.GetBytes("// byte[]....");
var ImagefileName = "sampleImage.jpg";
var ms = new MemoryStream();
var writer = new StreamWriter(ms);
writer.Write(content);
writer.Flush();
ms.Position = 0;
ImagefileMock.Setup(_ => _.OpenReadStream()).Returns(ms);
ImagefileMock.Setup(_ => _.FileName).Returns(ImagefileName);
ImagefileMock.Setup(_ => _.Length).Returns(ms.Length);
UpdateMediaDto mediaDto = new() {
Id = Guid.Parse("f1659b04-85a3-4969-7d20-08da081a9616"),
wordId=Guid.Parse("2caf24aa-4d37-4f64-aa91-4a605798c35b"),
PrimaryImage=ImagefileMock.Object,
SecondaryImage1 = ImagefileMock.Object };
HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(mediaDto), Encoding.UTF8);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data");
//Act
var response = await _httpClient.PutAsync("api/v1/admin/words/d9823bdd-0d11-42e5-a804-4d59d393d2bc/medias/f47136e3-754a-4f2b-b5cc-08da2d91a92e", httpContent);
//Assert
response.EnsureSuccessStatusCode();
}
But Here I can't serialize the object using SerializeObject. when I execute this test case I get an error like
Newtonsoft.Json.JsonSerializationException : Self referencing loop detected for property 'Object' with type 'Castle.Proxies.IFormFileProxy'. Path 'PrimaryImage.Mock'.
How can I solve this problem... and is there any other ways to test API like this?
The proxy created by MOQ is causing an issue with the serialization in this case.
Consider using an actual FormFile instance which is derived from IFormFile.
[Fact]
public async Task PUT_Media_with_UpdateMediaDto_results_WordMediaDto_success() {
//Setup mock file using a memory stream
string content = System.Text.Encoding.UTF8.GetBytes("// byte[]....");
string ImagefileName = "sampleImage.jpg";
MemoryStream ms = new MemoryStream();
StreamWriter writer = new StreamWriter(ms);
writer.Write(content);
writer.Flush();
ms.Position = 0;
//create FormFile with desired data
IFormFile ImagefileMock = new FormFile(ms, 0, ms.Length, "name_from_form", ImagefileName);
UpdateMediaDto mediaDto = new() {
Id = Guid.Parse("f1659b04-85a3-4969-7d20-08da081a9616"),
wordId=Guid.Parse("2caf24aa-4d37-4f64-aa91-4a605798c35b"),
PrimaryImage=ImagefileMock,
SecondaryImage1 = ImagefileMock
};
HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(mediaDto), Encoding.UTF8);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data");
//Act
var response = await _httpClient.PutAsync("api/v1/admin/words/d9823bdd-0d11-42e5-a804-4d59d393d2bc/medias/f47136e3-754a-4f2b-b5cc-08da2d91a92e", httpContent);
//Assert
response.EnsureSuccessStatusCode();
}
It seems you need to use MultipartFormDataContent to build your form and add parts. To Stream objects use StreamContent.
var multiPartformData = new MultipartFormDataContent();
var streamContent = new StreamContent(ImagefileMock);
multiPartformData .Add(streamContent);

Calling AWS Lambda Function in C#

I'm trying to run a Lambda function from a console application. The idea is for it to run a quick fire & forget lambda function without waiting for lambda function to return. My code doesn't appear to be executing the lambda function at all though. I know the function works because I can run with the test. When I run the below code I just get a task cancelled exception.
var jsonSerializer = new JsonSerializer();
var lambdaConfig = new AmazonLambdaConfig() { RegionEndpoint = RegionEndpoint.USEast2 };
var lambdaClient = new AmazonLambdaClient(lambdaConfig);
using (var memoryStream = new MemoryStream())
{
jsonSerializer.Serialize(myData, memoryStream);
var lambdaRequest = new InvokeRequest
{
FunctionName = "MyFunction",
InvocationType = "Event",
PayloadStream = memoryStream
};
var result = Task.Run(async () => { return await lambdaClient.InvokeAsync(lambdaRequest); }).Result;
Does anyone have some insight into what I'm doing wrong?
Thanks!
You can pass your myData directly instead converting into MemoryStream, if the data is a valid JSON with double quotes.
In function name you can use the ARN or just the name. Both works fine for me in latest version AWSSDK.Lambda -Version 3.3.103.31
static readonly string awsAccessKey = "access key here";
static readonly string awsSecretKey = "secret key here";
private static BasicAWSCredentials awsCredentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey);
private static AmazonLambdaConfig lambdaConfig = new AmazonLambdaConfig() { RegionEndpoint = RegionEndpoint.USEast1 };
private static AmazonLambdaClient lambdaClient = new AmazonLambdaClient(awsCredentials, lambdaConfig);
public async Task<string> GetLambdaResponse(string myData)
{
var lambdaRequest = new InvokeRequest
{
FunctionName = "mylambdafunction",
Payload = myData
};
var response = await lambdaClient.InvokeAsync(lambdaRequest);
if (response != null)
{
using (var sr = new StreamReader(response.Payload))
{
return await sr.ReadToEndAsync();
}
}
return string.Empty;
}
I believe there are two issues in your code:
(Mentioned by #Nikosi) You dispose your memoryStream before it is used for lambda invocation
(The fix that helped in my case) When you serialize you payload into memory stream, the position in the stream points to the byte after its end and thus SDK has nothing to read from it. So I just used memoryStream.Seek(0L, SeekOrigin.Begin)
By the way, assuming that JsonSerializer is the one from Newtonsoft.Json package, I didn't find Serialize method that accepts Stream parameter, only TextWriter or JsonWriter. So it might be necessary to wrap it into StreamWriter and make sure you call Flush or FlushAsync (or dispose StreamWriter before using memory stream as Lambda payload) like this:
await using var stream = new MemoryStream();
await using var streamWriter = new StreamWriter(stream);
var serializer = new JsonSerializer();
serializer.Serialize(streamWriter, payload);
await streamWriter.FlushAsync();
stream.Seek(0L, SeekOrigin.Begin);
log.LogInformation("Batch {0}: sending {1} messages to Lambda", batchId, batch.Count);
var lambdaResponse = await lambda.InvokeAsync(new InvokeRequest
{
InvocationType = InvocationType.RequestResponse,
PayloadStream = stream,
//Payload = JsonConvert.SerializeObject(payload),
FunctionName = lambdaArn
}, stoppingToken);
Mixing blocking calls could be causing a deadlock. If the intent is to fire and for get then just call the desired function. Also why give request a stream only to dispose of it after wards
public static void Main(string[] args) {
var jsonSerializer = new JsonSerializer();
var lambdaConfig = new AmazonLambdaConfig() { RegionEndpoint = RegionEndpoint.USEast2 };
var lambdaClient = new AmazonLambdaClient(lambdaConfig);
var memoryStream = new MemoryStream();
jsonSerializer.Serialize(myData, memoryStream);
var lambdaRequest = new InvokeRequest
{
FunctionName = "MyFunction",
InvocationType = "Event",
PayloadStream = memoryStream
};
lambdaClient.InvokeAsync(lambdaRequest);
Console.ReadLine();
}
The FunctionName in Nkosi's answer should actually be the entire ARN to your lambda function, so taking from Nkosi's answer:
public static void Main(string[] args) {
var jsonSerializer = new JsonSerializer();
var lambdaConfig = new AmazonLambdaConfig() { RegionEndpoint = RegionEndpoint.USEast2 };
var lambdaClient = new AmazonLambdaClient(lambdaConfig);
var memoryStream = new MemoryStream();
jsonSerializer.Serialize(myData, memoryStream);
var lambdaRequest = new InvokeRequest
{
FunctionName = "arn:aws:lambda:ap-southeast-2:{id}:function:MyFunction",
InvocationType = "Event",
PayloadStream = memoryStream
};
lambdaClient.InvokeAsync(lambdaRequest);
Console.ReadLine();

How to send ProtoBuf as bytes in HtttpClient? [duplicate]

I want to post this data to Web API server:
public sealed class SomePostRequest
{
public int Id { get; set; }
public byte[] Content { get; set; }
}
Using this code for server:
[Route("Incoming")]
[ValidateModel]
public async Task<IHttpActionResult> PostIncomingData(SomePostRequest requestData)
{
// POST logic here
}
and this - for client:
var client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:25001/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var content = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "id", "1" },
{ "content", "123" }
});
var result = await client.PostAsync("api/SomeData/Incoming", content);
result.EnsureSuccessStatusCode();
everything works fine (at least, debugger stops at breakpoint in PostIncomingData).
Since there is a byte array, I don't want to serialize it as JSON, and want to post it as binary data to decrease network traffic (something like application/octet-stream).
How this can be achieved?
I've tried to play with MultipartFormDataContent, but looks like I just can't understand, how MultipartFormDataContent will match signature of controller's method.
E.g., replacing content to this:
var content = new MultipartFormDataContent();
content.Add(new FormUrlEncodedContent(new Dictionary<string, string> { { "id", "1" } }));
var binaryContent = new ByteArrayContent(new byte[] { 1, 2, 3 });
binaryContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
content.Add(binaryContent, "content");
var result = await client.PostAsync("api/SomeData/Incoming", content);
result.EnsureSuccessStatusCode();
leads to error 415 ("Unsupported media type").
WebAPI v2.1 and beyond supports BSON (Binary JSON) out of the box, and even has a MediaTypeFormatter included for it. This means you can post your entire message in binary format.
If you want to use it, you'll need to set it in WebApiConfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Formatters.Add(new BsonMediaTypeFormatter());
}
}
Now, you an use the same BsonMediaTypeFormatter at the client side to serialize your request:
public async Task SendRequestAsync()
{
var client = new HttpClient
{
BaseAddress = new Uri("http://www.yourserviceaddress.com");
};
// Set the Accept header for BSON.
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/bson"));
var request = new SomePostRequest
{
Id = 20,
Content = new byte[] { 2, 5, 7, 10 }
};
// POST using the BSON formatter.
MediaTypeFormatter bsonFormatter = new BsonMediaTypeFormatter();
var result = await client.PostAsync("api/SomeData/Incoming", request, bsonFormatter);
result.EnsureSuccessStatusCode();
}
Or, you can use Json.NET to serialize your class to BSON. Then, specify you want to use "application/bson" as your "Content-Type":
public async Task SendRequestAsync()
{
using (var stream = new MemoryStream())
using (var bson = new BsonWriter(stream))
{
var jsonSerializer = new JsonSerializer();
var request = new SomePostRequest
{
Id = 20,
Content = new byte[] { 2, 5, 7, 10 }
};
jsonSerializer.Serialize(bson, request);
var client = new HttpClient
{
BaseAddress = new Uri("http://www.yourservicelocation.com")
};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/bson"));
var byteArrayContent = new ByteArrayContent(stream.ToArray());
byteArrayContent.Headers.ContentType = new MediaTypeHeaderValue("application/bson");
var result = await client.PostAsync(
"api/SomeData/Incoming", byteArrayContent);
result.EnsureSuccessStatusCode();
}
}
I convert Byte Array into Base64 String to post:
await client.PostAsJsonAsync( apiUrl,
new {
message = "",
content = Convert.ToBase64String(yourByteArray),
}
);
and receiver can convert the Base64 String back to Byte Array by:
string base64Str = (string)postBody.content;
byte[] fileBytes = Convert.FromBase64String(base64Str);
I have created this generic and cross platform method to support the BSON format using the Json.NET library so we can reuse it easier later. It works fine in Xamarin platform as well.
public static async HttpResponseMessage PostBsonAsync<T>(string url, T data)
{
using (var client = new HttpClient())
{
//Specifiy 'Accept' header As BSON: to ask server to return data as BSON format
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/bson"));
//Specify 'Content-Type' header: to tell server which format of the data will be posted
//Post data will be as Bson format
var bSonData = HttpExtensions.SerializeBson<T>(data);
var byteArrayContent = new ByteArrayContent(bSonData);
byteArrayContent.Headers.ContentType = new MediaTypeHeaderValue("application/bson");
var response = await client.PostAsync(url, byteArrayContent);
response.EnsureSuccessStatusCode();
return response;
}
}
The method to help to serialise data to BSON format:
public static byte[] SerializeBson<T>(T obj)
{
using (MemoryStream ms = new MemoryStream())
{
using (BsonWriter writer = new BsonWriter(ms))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(writer, obj);
}
return ms.ToArray();
}
}
Then you can use the Post method like this:
var response = await PostBsonAsync<SamplePostRequest>("api/SomeData/Incoming", requestData);
Fyi, for protobuf serialization to request body posts
LoginRequest loginRequest = new LoginRequest()
{
Code = "UserId",
Password = "myPass",
CMToken = "eIFt4lYTKGU:APA91bFZPe3XCDL2r1JUJuEQLlN3FoeFw9ULpw8ljEavNdo9Lc_-Qua4w9pTqdOFLTb92Kf03vyWBqkcvbBfYEno4NQIvp21kN9sldDt40eUOdy0NgMRXf2Asjp6FhOD1Kmubx1Hq7pc",
};
byte[] rawBytes = ProtoBufSerializer.ProtoSerialize<LoginRequest>(loginRequest);
var client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:9000/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/x-protobuf"));
//var bSonData = HttpExtensions.SerializeBson<T>(data);
var byteArrayContent = new ByteArrayContent(rawBytes);
byteArrayContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-protobuf");
var result = client.PostAsync("Api/Login", byteArrayContent).Result;
Console.WriteLine(result.IsSuccessStatusCode);
I wanted to send it truly binary like I did with WebClient before not make it multipart.
Using inspiration from this question I got it working this way:
HttpClient InternalHttpClient = new HttpClient();
HttpContent BinaryContent = new ByteArrayContent(new byte[] { 1, 2, 3 });
byte[] ReceivedData = new byte[0];
using (HttpResponseMessage ResponseMessage = InternalHttpClient.PostAsync("apiurl/binarycomms.aspx", BinaryContent).Result)
{
using (HttpContent ResponseBytes = ResponseMessage.Content)
{
ReceivedData = ResponseBytes.ReadAsByteArrayAsync().Result;
}
}
On the server side the code is also fully binary:
protected void Page_Load(object sender, EventArgs e)
{
Page.Response.ContentType = "application/octet-stream";
byte[] Challenge = Page.Request.BinaryRead(Request.TotalBytes);
Page.Response.BinaryWrite(new byte[] { 10, 20, 30 });
}
You can easily add compression to this communication to make the bandwidth usage even smaller.
Love to hear comments should I have missed something or if this is off topic, but it works like a charm for me.

How to pass an object as a parameter in HttpWebRequest POST?

Here I am calling Restful WCF service from my web application and I don't know how to pass an object as parameter in this one. Here is my client code:
protected void Button1_Click(object sender, EventArgs e)
{
UserInputParameters stdObj = new UserInputParameters
{
AssociateRefId = "323",
CpecialLoginId = "a#gmail.com",
PartnerId = "aaaa",
FirstName = "aaaa",
LastName = "bbbb",
Comments = "dsada",
CreatedDate = "2013-02-25 15:25:47.077",
Token = "asdadsadasd"
};
string url = "http://localhost:13384/LinkService.svc/TokenInsertion";
try
{
ASCIIEncoding encoding = new ASCIIEncoding();
System.Net.WebRequest webReq = System.Net.WebRequest.Create(url);
webReq.Method = "POST";
webReq.ContentType = "application/json; charset=utf-8";
DataContractJsonSerializer ser = new DataContractJsonSerializer(stdObj.GetType());
StreamWriter writer = new StreamWriter(webReq.GetRequestStream());
writer.Close();
webReq.Headers.Add("URL", "http://localhost:13381/IntegrationCheck/Default.aspx");
System.Net.WebResponse webResp = webReq.GetResponse();
System.IO.StreamReader sr = new System.IO.StreamReader(webResp.GetResponseStream());
string s = sr.ReadToEnd().Trim();
}
catch (Exception ex)
{
}
}
And my service method:
public string UserdetailInsertion(UserInputParameters userInput)
You have to parse the object in the format and write it into the RequestStream.
Your class
[Serializable]
class UserInputParameters {
"your properties etc"
};
The code to serialize the object
private void SendData(UserInputParameters stdObj) {
DataContractJsonSerializer ser = new DataContractJsonSerializer(stdObj.GetType());
StreamWriter writer = new StreamWriter(webReq.GetRequestStream());
JavaScriptSerializer jss = new JavaScriptSerializer();
// string yourdata = jss.Deserialize<UserInputParameters>(stdObj);
string yourdata = jss.Serialize(stdObj);
writer.Write(yourdata);
writer.Close();
}
This should be the trick.
The class JavaScriptSerializer is located in the namespace System.Web.Script.Serialization which can be found in the assembly System.Web.Extensions (in System.Web.Extensions.dll) here is the MSDN Article: http://msdn.microsoft.com/en-us/library/bb337131.aspx
We can not send an Object data to the remote server from server side code using WebRequest class in C# as we can send only stream data to the remote server and object representation in memory is not stream.Hence before sending the object we need to serialize it as a stream and then we are able to send it to the remote server.Below is the complete code.
namespace SendData
{
public class SendObjectData
{
static void Main(string[] args)
{
Employee emp = new Employee();
emp.EmpName = "Raju";
emp.Age = 30;
emp.Profession = "Teacher";
POST(emp);
}
// This method post the object data to the specified URL.
public static void POST(Employee objEmployee)
{
//Serialize the object into stream before sending it to the remote server
MemoryStream memmoryStream = new MemoryStream();
BinaryFormatter binayformator = new BinaryFormatter();
binayformator.Serialize(memmoryStream, objEmployee);
//Cretae a web request where object would be sent
WebRequest objWebRequest = WebRequest.Create(#"http://localhost/XMLProvider/XMLProcessorHandler.ashx");
objWebRequest.Method = "POST";
objWebRequest.ContentLength = memmoryStream.Length;
// Create a request stream which holds request data
Stream reqStream = objWebRequest.GetRequestStream();
//Write the memory stream data into stream object before send it.
byte[] buffer = new byte[memmoryStream.Length];
int count = memmoryStream.Read(buffer, 0, buffer.Length);
reqStream.Write(buffer, 0, buffer.Length);
//Send a request and wait for response.
try
{
WebResponse objResponse = objWebRequest.GetResponse();
//Get a stream from the response.
Stream streamdata = objResponse.GetResponseStream();
//read the response using streamreader class as stream is read by reader class.
StreamReader strReader = new StreamReader(streamdata);
string responseData = strReader.ReadToEnd();
}
catch (WebException ex) {
throw ex;
}
}
}
// This is an object that needs to be sent.
[Serializable]
public class Employee
{
public string EmpName { get; set; }
public int Age { get; set; }
public string Profession { get; set; }
}
}

Send XML String as Response

I am getting my Request from a third party application(different domain) to my ASP application. I am handling the request and doing the business part in my application and as a acknowledgement I need to send XML string as Response to the same Page which POSTED the request to my Application. I was successful in retrieving the input from Request using the following code
NameValueCollection postPageCollection = Request.Form;
foreach (string name in postPageCollection.AllKeys)
{
... = postPageCollection[name]);
}
But i am not sure how to send back the response along with XML String to the site(different domain)?
EDIT: How to get the URL from where the POST happened.
You can get the url that come from Request.ServerVariables["HTTP_REFERER"]
For the XML, here are 2 functions that I use
public static string ObjectToXML(Type type, object obby)
{
XmlSerializer ser = new XmlSerializer(type);
using (System.IO.MemoryStream stm = new System.IO.MemoryStream())
{
//serialize to a memory stream
ser.Serialize(stm, obby);
//reset to beginning so we can read it.
stm.Position = 0;
//Convert a string.
using (System.IO.StreamReader stmReader = new System.IO.StreamReader(stm))
{
string xmlData = stmReader.ReadToEnd();
return xmlData;
}
}
}
public static object XmlToObject(Type type, string xml)
{
object oOut = null;
//hydrate based on private string var
if (xml != null && xml.Length > 0)
{
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(type);
using (System.IO.StringReader sReader = new System.IO.StringReader(xml))
{
oOut = serializer.Deserialize(sReader);
sReader.Close();
}
}
return oOut;
}
And here is an example how I use it
[Serializable]
public class MyClassThatKeepTheData
{
public int EnaTest;
}
MyClassThatKeepTheData cTheObject = new MyClassThatKeepTheData();
ObjectToXML(typeof(MyClassThatKeepTheData), cTheObject)
Cant you just use the following code:
Request.UrlReferrer.ToString();

Categories

Resources