Get value from IActionResult - asp.net

I have Controller whit some endpoints Task<IActionResult> MyCustomEndpoint which is returning return Ok(CustomDataType). Returned datas are in JSON fromat.
Now I want to call that Endpoint from other Controller like var resp = myController.MyCustomEndpoint, where resp becomes IActionResult. The problem is that resp now doesn't return only datas anymore, but all of those fields as seen on image.
My question is, how to access and return only Value field, because resp.Value is not working.
Thanks for help.

You have to convert to as ObjectResult
public async Task GetFormSummary_ItShouldReturnSingleForm_NotNull()
{
var formId = new Guid("5EF685E7-1167-4226-7F5E-08D9009544A3");
var mockFormService = new Mock<IFormService>();
mockFormService.Setup(x => x.GetAsync(formId).Result)
.Returns(GetTestForm());
// Inject
var formController = new FormController(_logger, mockFormService.Object);
// Act
var result = (await formController.GetAsync(formId)) as ObjectResult;
// Assert
Assert.IsAssignableFrom<FormViewModel>(result.Value);
}

Related

How to capture response after calling REST API?

I am using RestSharp to call REST API as
public async Task<IActionResult> getoutput()
{
var client = new RestClient("....");
var request = new RestRequest(".....");
var response = await client.ExecuteAsync(request);
return Ok(response.Content);
}
My response is like
{
"number" : 567889
}
I want to get that number 567889 and save it into variable in my controller. But I am not able to do so.
I tried with
var answer = response.Content;
But it is showing the JSON.
Can somebody please help me out?
you can create a class for your data
public class Answer
{
public int number {get;set;}
}
and action
var response = await client.ExecuteAsync(request);
Answer answer= JsonConvert.DeserializeObject<Answer>(response.Content);
int number=answer.number;
return Ok(answer);
or if for some reason you don't want to create a class, you can parse a json string
var response = await client.ExecuteAsync(request);
int _number= (int) JObject.Parse(response.Content)["number"]
return Ok( new { number= _number} );

Get the Result from a list of Task

I know this has been asked before, but I simply cannot figure out how to do this right.
So, the below code is obviously wrong in the sense that I am awaiting something in a query.
// GET: /<controller>/
[HttpGet]
public new IActionResult Index()
{
var model = new List<Models.ViewModels.ApplicationUser.ListViewModel>();
model = _userManager.Users.Select(u => new Models.ViewModels.ApplicationUser.ListViewModel
{
Id = u.Id,
Email = u.Email,
Name = u.GivenName + " " + u.SurName,
RoleNames = await _userManager.GetRolesAsync(u)
}).ToList();
return View(model);
}
This makes the following error show: "the "await" operator can only be used within an async lambda expression".
So, I finalize the query first and I make the lambda async:
// GET: /<controller>/
[HttpGet]
public new IActionResult Index()
{
var model = new List<Models.ViewModels.ApplicationUser.ListViewModel>();
// get users first, so I don't have to async something in a Select
var users = _userManager.Users.ToList();
// make the lambda asyc
model = users.Select(async u => new Models.ViewModels.ApplicationUser.ListViewModel
{
Id = u.Id,
Email = u.Email,
Name = u.GivenName + " " + u.SurName,
RoleNames = await _userManager.GetRolesAsync(u)
}).ToList();
return View(model);
}
But then I get Cannot implicitly convert type 'System.Collections.Generic.List<System.Threading.Tasks.Task<Models.ViewModels.ApplicationUser.ListViewModel>>' to 'System.Collections.Generic.List<Models.ViewModels.ApplicationUser.ListViewModel>'
So basically (I guess) it says I have a list of Task of which I should get the result. But how do I get the result from this Task? Or better: what is the best way to go about this?
I've checked this and this and this without getting closer.
Your variable named model is of the type List<Task<ApplicationUser>>. To get a List<ApplicationUser> you just need to await all of the tasks. Also, right now the call to get all users is the blocking variant you can switch that out for ToListAsync. Try this instead:
[HttpGet]
public async Task<IActionResult> Index() {
var model = new List<Models.ViewModels.ApplicationUser.ListViewModel>();
// get users first, so I don't have to async something in a Select
var users = await _userManager.Users.ToListAsync();
// make the lambda asyc
modelTasks = users.Select(async u => new Models.ViewModels.ApplicationUser.ListViewModel {
Id = u.Id,
Email = u.Email,
Name = u.GivenName + " " + u.SurName,
RoleNames = await _userManager.GetRolesAsync(u)
}).ToList();
var users = await Task.WhenAll(modelTasks);
return View(users);
}

Response on created context keeps giving me NullStream

I'm trying to write a middleware for batch requests i .net core 2.0.
So far the I have splitted the request, pipe each request on to the controllers.
The controllers return value, but for some reason the response on the created context that I parse to the controllers keeps giving me a NullStream in the body, so I think that there is something that I miss in my setup.
The code looks like this:
var json = await streamHelper.StreamToJson(context.Request.Body);
var requests = JsonConvert.DeserializeObject<IEnumerable<RequestModel>>(json);
var responseBody = new List<ResponseModel>();
foreach (var request in requests)
{
var newRequest = new HttpRequestFeature
{
Body = request.Body != null ? new MemoryStream(Encoding.ASCII.GetBytes(request.Body)) : null,
Headers = context.Request.Headers,
Method = request.Method,
Path = request.RelativeUrl,
PathBase = string.Empty,
Protocol = context.Request.Protocol,
Scheme = context.Request.Scheme,
QueryString = context.Request.QueryString.Value
};
var newRespone = new HttpResponseFeature();
var requestLifetimeFeature = new HttpRequestLifetimeFeature();
var features = CreateDefaultFeatures(context.Features);
features.Set<IHttpRequestFeature>(newRequest);
features.Set<IHttpResponseFeature>(newRespone);
features.Set<IHttpRequestLifetimeFeature>(requestLifetimeFeature);
var innerContext = _factory.Create(features);
await _next(innerContext);
var responseJson = await streamHelper.StreamToJson(innerContext.Response.Body);
I'm not sure what it is I'm missing in the setup, since innerContext.Response.Body isn't set.
One of the endpoints that I use for testing and that gets hit looks like this
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
I found the error, or two errors for it to work.
First I had to change my newResponse to
var newRespone = new HttpResponseFeature{ Body = new MemoryStream() };
Since HttpResponseFeature sets Body to Stream.Null in the constructor.
When that was done, then Body kept giving an empty string when trying to read it. That was fixed by setting the Position to Zero like
innerContext.Response.Body.Position = 0;

How to Unit test an AsyncTask which await another Async task?

public async Task<ResModel> GetDetails()
{
ResModel resp = new ResModel();
resp = await MobController.GetAllDeatails();
return resp;
}
In the await this calls for an async task method named GetAllDeatails and returns an object ResModel.
How to properly create an unit test for this?
The unit test I've created is right below:
[TestMethod]
public async Task GetFromGetDetails()
{
var controller = new SevicesController();
ResModel resp = new ResModel();
using(ShimsContext.Create())
{
ProjectAPI.Fakes.ShimMobController.GetAllDeatails = () => {
resp.MessageType = "Get"
resp.Message ="contdetail";
return resp;
};
returnValueOfAsyncTask = await controller.GetDetails();
Assert.IsNotNull(returnValueOfAsyncTask);
}
}
This gives errors in the ShimContext creation because the return type must be async in GetAllDeatails but here it only returns the object.
Following is the main error I'm getting:
Error CS0029 Cannot implicitly convert type
'ProjectAPI.Models.ResModel' to
'System.Threading.Tasks.Task<ProjectAPI.Models.ResModel>'
Un‌​itTestProjectAPI
The error message clearly states that it cannot convert the ResModel to a Task<ResModel> which is the return type of the method being shimmed.
In the shim you are returning the model when the method is suppose to be returning a Task. Use Task.FromResult in order to wrap the model in a Task so that it can be return and awaited.
In the exercising of the method under test you stated that the variable used to hold the result of the await was a Task<ResModel>. That should be changed because when you await a Task that returns a result it will just return the result not the task. So that result variable needs to be changed to from Task<ResModel> to ResModel.
Here is the update unit test based on above changes.
[TestMethod]
public async Task GetFromGetDetails() {
//Arrange
var controller = new SevicesController();
var expected = new ResModel();
using(ShimsContext.Create()) {
ProjectAPI.Fakes.ShimMobController.GetAllDeatails = () => {
expected.MessageType = "Get"
expected.Message ="contdetail";
return Task.FromResult(expected);
};
//Act
var actual = await controller.GetDetails();
//Assert
Assert.IsNotNull(actual);
Assert.AreEqual(expected, actual);
}
}
Change the Method return type
to
(public async Task
<
ResModel> GetFromGetDetails()

Accessing the returned XML from an API call

I have the following action method to perform an API call:-
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Rack rack, FormCollection formValues)
{
if (ModelState.IsValid) {
using (var client = new WebClient())
{
var query = HttpUtility.ParseQueryString(string.Empty);
foreach (string key in formValues)
{
query[key] = this.Request.Form[key];
}
query["username"] = "testuser";
query["password"] = ///.....
query["assetType"] = "Rack";
query["operation"] = "AddAsset";
var url = new UriBuilder("http://win-spdev:8400/servlets/AssetServlet");
url.Query = query.ToString();
try
{
string xml = client.DownloadString(url.ToString());
}
The return XML from the API call looks as follow:-
<operation>
<operationstatus>Failure</operationstatus>
<message>Rack already exists.Unable to add</message>
</operation>
but how i can reach the message and operationstaus and according to them to display an appropriate message . i use to serialize the returned Json such as , but i am not sure how to do so for the xML:-
var serializer = new JavaScriptSerializer();
var myObject = serializer.Deserialize<newprocess>(json);
string activityid = myObject.activityId;
Just load it into an XmlDocument.
Untested and from the top of my head:
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(theXML);
var status = xmlDoc.SelectSingleNode("/operation/operationstatus").InnerText;
var message = xmlDoc.SelectSingleNode("/operation/message").InnerText;
If you using ASP.NET mvc, I believe you can use HttpClient, instead of WebClient:
Define result class:
public class operation
{
public string operationstatus{get;set;}
public string message{get;set;}
}
And then use it for automatic deserilization:
var client = new HttpClient();
var result = client.PostAsync(url,
new FormUrlEncodedContent(new Dictionary<string, string>{
{"username","testuser"},
{"assetType","Rack"}}))
.Result.Content
.ReadAsAsync<operation>().Result;

Resources