C# - Get dynamic URL Parameter on API call - c#

I'm building an movie API using C# where the user calls my endpoint and based on the id passed, my server calls the movie db api to get some details.
For example: if a user calls the "/movie/id" endpoint, the server gets that id and pass it to the movieDb.Get method.
My main issue is on retrieving that id the user passes in the url when accessing my endpoint
This is what i've been trying:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/movie/{id}", (id) =>
{
object response = movieDb.Get($"/movie/{id}");
return response;
});
and my class:
public class MovieDB{
public async Task<object> Get(string uri){
try{
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync($"{baseUrl}/{uri}?
{apiKey}");
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
return responseBody;
}
catch (Exception){
throw;
}
}
}
When i access "http://localhost:port/movie/616037", i expect to see the movie db return to this movie, but i get "conecction was recused by the localhost".
If i force and id like
string id = "616037"
and then call this method sending the correct endpoint on movie DB API, then it returns this movie details
e.g.
movieDB.Get($"/movie/{id}")

You need to specify parameter. Because without specifying id is HttpContext
Your code must look like this
app.MapGet("/movie/{id}", (int id) =>{
...
}

Related

.NET API Controller controller using Entity Framework Get actions functionnal, but PUT and POST give missing responses

I am working on an api that allows managment of contacts.
I've generated my Entity Framework Context, Models, and Controllers.
My Api request are made in a Proxy class (called APIHelper) that contains methods to be used in my app.
My API has no problem returning results when calling the Get methods to fetch my list of Contacts, but when sending a PUT or POST request.
These Request actually work, the Instructions contained within each Method are executed correctly, PUT modifies my Contacts, POST creates a new Contacts, but reaching the end of either methods, right after it returns, the Program stops, or at least it looks like it.
There are no feedbacks from either the API which looks like it did its job, and the Proxy class which still seems to be awaiting the response from the API.
Here is the code doing the Request from the Proxy APIHandler Class :
public static async Task<bool> PostEdiContact(EdiContact ediContact)
{
string query = $"{ApiPred}/api/EdiContacts";
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(query);
//HTTP POST
var result = await client.PostAsJsonAsync(query, ediContact);
return result.IsSuccessStatusCode;
}
}
Here is the code From the controller :
[ResponseType(typeof(EdiContact))]
public async Task<IHttpActionResult> PostEdiContact(EdiContact ediContact)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.EdiContacts.Add(ediContact);
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateException e)
{
if (EdiContactExists(ediContact.contactID))
{
return Conflict();
}
else
{
throw;
}
}
return CreatedAtRoute("DefaultApi", new { id = ediContact.contactID }, ediContact);
}
This last return is where the next execution just seems to go into the beyond as I have no clue about where it goes next. It works the fine for the Get Methods, but not these.
I have found no similar cases online and no one around me can help me with it.
As an additional ressources, here is the WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config
.Formatters
.JsonFormatter
.SerializerSettings
.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
// Removing Xml formatter
config.Formatters.Remove(config.Formatters.XmlFormatter);
}
}
Testing the request using swagger also returns an a response with code 201 so everything seems fine. but my Proxy Class doesn't get anything awaiting the response.
So I couldn't get it to work by using the PostAsJsonAsync() method from the HttpClient class.
What I did to work around this issue is using the basic SendAsync() method.
It is a bit more work since you need to declare and initialise an HttpRequestMessage, but here is what it looks like :
public static async Task<bool> PostEdiContact(EdiContact ediContact)
{
string json = JsonConvert.SerializeObject(ediContact);
using (HttpClient client = new HttpClient())
{
string url = $"{ApiPred}/api/EdiContact";
using(HttpRequestMessage request = new
HttpRequestMessage(HttpMethod.Post, url))
{
StringContent stringContent = new StringContent(
json,
Encoding.UTF8,
"application/json");
request.Content = stringContent;
HttpResponseMessage response = await client.SendAsync(
request,
HttpCompletionOption.ResponseHeadersRead)
.ConfigureAwait(false);
if (!response.IsSuccessStatusCode)
throw new Exception("An error occured");
response.EnsureSuccessStatusCode();
return true;
}
}
}

How to a Pass Parameter from Endpoint to API Controller

I'm new to programing and have been following a tutorial. I have been able to pass a parameter from my View to my Endpoint...as well as from my API Controller to the SQL Server Stored Procedure. The Parameter will get to the Endpoint but isn't passed to the controller...if I manually pass that parameter through when debugging, it will return the correct data to the View. So what I can't seem to figure out is how to pass the parameter from the Endpoint to the controller.
Endpoint:
public async Task<List<GroupModel>> GetGroupById(int groupId)
{
using (HttpResponseMessage response = await _apiHelper.ApiClient.GetAsync($"/api/FeedGroup/GetGroupById/{groupId}")
{
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsAsync<List<GroupModel>>();
return result;
}
else
{
throw new Exception(response.ReasonPhrase);
}
}
API Controller:
[HttpGet("GetGroupById/{GroupId:int}")]
[Route("GetGroupById")]
public List<GroupModel> GetGroupById(int GroupId)
{
int groupId = GroupId;
return _GroupData.GetGroupById(groupId);
}
Also for info, you are calling an Asynchronous method in your controller over a synchronous HttpGet method here. Thats not a good solution.
A better solution would be the following:
[HttpGet]
[Route("GetGroupById")]
public async Task<List<GroupModel>> GetGroupById(int GroupId)
{
int groupId = GroupId;
return await _GroupData.GetGroupById(groupId);
}

Unable to send form data to web api using postasync

I am trying to send sourceFile value to web api. But in API i am receiving is null
var formVars = new Dictionary<string, string>();
formVars.Add("sourceFile", "Helloo");
HttpContent content = new FormUrlEncodedContent(formVars);
var result = client.PostAsync("ImageApi/Compare", content).Result;
string resultContent = result.Content.ReadAsStringAsync().Result;
return Content(resultContent);
API code
[HttpPost()]
public ActionResult Compare(string sourceFile)
{
return Ok(sourceFile);
}
I am using DotNet core 2.0
you need to await the result, do not try to access .Result yourself. The call would not have completed at that point.
you need to use something like this:
HttpContent content = new FormUrlEncodedContent(formVars);
var result = await client.PostAsync("ImageApi/Compare", content);
result .EnsureSuccessStatusCode();
string responseBody = await result.Content.ReadAsStringAsync();
This is based on your code and hasn't been tested but should set you on the right path to get this working. Don't ever try to do async stuff by accessing .Result.
One more thing, you need to use a model as well.
create a model class, which has all the properties you add in your dictionary.
in your case it will be something like :
public class MyModel{
public string sourceFile { get ;set; }
}
your controller becomes:
[HttpPost()]
public ActionResult Compare([FromBody]MyModel model)
{
return Ok(model.sourceFile);
}

How to accept a query and return an async task?

I am getting the following exception:
Cannot create an EDM model as the action 'Get' on controller 'Accounts' has a return type 'System.Web.Http.IHttpActionResult' that does not implement IEnumerable<T>.
When attempting to query my endpoint:
http://localhost:8267/api/accounts
The AccountsController that is doing the work:
public async Task<IHttpActionResult> Get(ODataQueryOptions options)
{
var query = options.Request.RequestUri.PathAndQuery;
var client = new HttpClient();
var crmEndPoint = #"HTTPS://MYCRMORG.COM/API/DATA/V8.1/";
HttpResponseMessage response = await client.GetAsync(crmEndPoint+query);
object result;
if (response.IsSuccessStatusCode)
{
result = await response.Content.ReadAsAsync<object>();
return Ok(result);
}
return NotFound();
}
What am I doing wrong? How do I simply add the PathAndQuery to my crmEndPoint and return the result?
The OData framework provides extra response formatting/querying rules on top of plain Web API.
Using ODataQueryOptions parameter requires that the action method returns either IQueryable<T> or IEnumerable<T>.
ODataQueryOptions just helps to parse the incoming OData request url making parameters such as $filter and $sort accessible through properties.
Your code doesn't need this service because all it does is just redirect the request to the crmEndPoint. So, instead of using options.Request you can access the request object through the Request property of the controller and drop the parameter altogether.
Here's the code:
public async Task<IHttpActionResult> Get()
{
var query = Request.RequestUri.PathAndQuery;
var client = new HttpClient();
var crmEndPoint = #"HTTPS://MYCRMORG.COM/API/DATA/V8.1/";
HttpResponseMessage response = await client.GetAsync(crmEndPoint + query);
object result;
if (response.IsSuccessStatusCode)
{
result = await response.Content.ReadAsAsync<object>();
return Ok(result);
}
return NotFound();
}

Http GET call to API endpoint with complex object from MVC controller

I have to retrieve orders from my API made in NET Core.
The retrieval is made in an action of my MVC controller calling an endpoint of another NET Core APP using GET.
The API endpoint is the following one:
API:
[HttpGet("orders/orderSearchParameters")]
public IActionResult Get(OrderSearchParameters orderSearchParameters)
{
var orders = MenuService.GetMenuOrders(new GetMenuOrdersRequest { From = orderSearchParameters.From, To = orderSearchParameters.To, FoodProviderId = orderSearchParameters.FoodProviderId }).Orders;
return Ok(orders);
}
An action of my Web App MVC controller must call that endpoint, and for that this is the following code:
public IActionResult GetOrders(OrderSearchParametersModel orderSearchParameters)
{
var uri = string.Format(ApiUri + "menus/orders/");
using (HttpClient httpClient = new HttpClient())
{
var response = httpClient.GetStringAsync(uri);
if (response.IsCompleted)
{
var orders = JsonConvert.DeserializeObject<List<OrderModel>>(response.Result);
return Ok(orders);
}
else
{
return BadRequest();
}
}
}
What I canĀ“t find is how can I serialize OrderSearchParametersModel to perform the GET operation with the HttpClient in the MVC controller.
In the attached code I do the GET without the incoming object.
How can I send this object using GET operation with HttpClient?
If you put all your parameters in the querystring, they will be translated into an OrderSearchParametersModel but they need to match this model properties names.

Categories