API works fine but parameters are not accepted c# - c#

I have my route prefix here:
[RoutePrefix("api/Adresses")]
public class AdressesController : ApiController
{
My function here:
[Route("{codeEtudiant}")]
// GET: api/Adresses/1
public IEnumerable<Object> getAdresseEtu(Int32 code)
{
Where I call my api:
using (var client2 = new HttpClient())
{
string getasync = "http://localhost:11144/api/Adresses/" + etu.Code;
var response2 = await client.GetAsync(getasync);
var json2 = await response.Content.ReadAsStringAsync();
int cpt2 = -1;
foreach (object tmp2 in JsonConvert.DeserializeObject<List<Object>>(json2))
{
My string getasync returns: http://localhost:11144/api/Adresses/1
With these methods I can call any function in my api that does not have parameters but as soon I have one it doesn't respond and give me a response:
404 reason(not found)

The parameter names have to match. Currently you have the route parameter named codeEtudiant but the parameter of the method named code. Give them both the same name.
[Route("{codeEtudiant}")]
public IEnumerable<Object> getAdresseEtu(Int32 codeEtudiant)
See also Attribute Routing in ASP.NET Web API 2.

The error is because the Route Attribute must have the same name of the parameter, use
[Route("{code}")]

Related

How can I send URL parameter in ASP.NET Core Web API parameters

I wrote this code in a C# ASP.NET Core Web API project:
[HttpGet]
[Route("GetShortURL/{_url}/{tokenPass}")]
[ApiExplorerSettings(GroupName = "ShortURL")]
public ActionResult<ServiceResult<string>> GetShortURL(string _url, string tokenPass)
When I enter this parameter as _url, I get an error:
Error: Not Found
https://github.com/VahidN/DNTPersianUtils.Core
http://...//GetShortURL/https%3A%2F%2Fgithub.com%2FVahidN%2FDNTPersianUtils.Core/TokenPass
How can I call this API with the first Web URL parameter?
when i change the [Route("GetShortURL/{_url}/{tokenPass}")] to [Route("GetShortURL")] the problem was solved but i want to send query by / not by ?
for example, i want to call API like this :
1- http://..../GetShortURL/_UrlParam/_TokenPassParam
not like below :
2- http://..../GetShortURL?_url=_urlParam&tokenPass=_TokenPassParam
the second way works fine but I want first way to work correctly when i pass an URL like this
https%3A%2F%2Fgithub.com%2FVahidN%2FDNTPersianUtils.Core
can anyone help me?
First approach:
Pass the params you want as query string and then change the method like below:
[HttpGet("GetShortURL")]
[ApiExplorerSettings(GroupName = "ShortURL")]
public ActionResult<ServiceResult<string>> GetShortURL(string _url, string tokenPass)
Then For extracting the different parts of the url (protocol, domain name, path and query string), use the code below (path is an array separated by slash):
try
{
var decodedUrl = System.Web.HttpUtility.UrlDecode(_url);
Uri uri = new Uri(decodedUrl);
var scheme = uri.Scheme;
var host = uri.Host;
var absolutePathSeperatedBySlash = uri.AbsolutePath.Split('/').Skip(1).ToList();
var query = uri.Query;
// rest of the code ...
}
catch (Exception ex)
{
//...
}
Second approach:
If you want it to be sent as a url parameter, first you have to encode the value of _url with encodeURIComponent() in javascript, to make sure that some special characters like , / ? : # & = + $ # are changed.
Then:
[HttpGet("GetShortURL/{_url}/{tokenPass}")]
[ApiExplorerSettings(GroupName = "ShortURL")]
public ActionResult<ServiceResult<string>> GetShortURL(string _url, string tokenPass)
The rest is just like the method body of the first approach.
With the following url
http://...//GetShortURL/https%3A%2F%2Fgithub.com%2FVahidN%2FDNTPersianUtils.Core/TokenPass
The value of _url will be:
If you want to convert it to a correct url,you needs to replace %2F with / in GetShortURL:
var url = _url.Replace("%2F","/");
just make parameters to be optional
[HttpGet("GetShortURL/{_url?}/{tokenPass?}")]
public ActionResult<ServiceResult<string>> GetShortURL(string _url, string tokenPass)
in this case you can call the action without any parameters, with one parameter or with two parameters

How to call one service from another with parameter and get response

Currently, I have two services running at different endpoints. For example (this is not my real scenario):
StudentService
CheckHomeWorkService
CheckHomeWorkService can be used from many services (For example TeacherService, WorkerService). It has one controller with CheckHomeWork action. It has some parameters:
HomeWorkNumber (int)
ProvidedSolution (string).
It will return success or failed.
Now, In my StudentService, I have a controller with SubmitHomeWork Action. It needs to check homework using CHeckHomeWorkService and save results to a database. How can I implement this?
I was using Ocelot Api GateWay but it can 'redirect' to another service and I need to save the result of the response to the database
As suggested in the comments, you can use HttpClient to call the other APIs. However, if you want a more safe and performant solution, you can use also the HttpClientFactory.
see this why to use it
and see the official docu
After your comment you say that you have separate WEB API services
in this case you can do this service to retrieve the result :
public async Task<List<HomeWorkModel>> CheckHomeWorkService(int
homeWorkNumber, string providedSolution)
{
using (var httpClient = new HttpClient())
{
using (var response = await
httpClient.GetAsync(Constants.ApiBaseUrl + "/CheckHomeWork?n=" +
homeWorkNumber + "&sol=" + providedSolution))
{
if (response.StatusCode ==
System.Net.HttpStatusCode.OK)
{
string apiResponse = await
response.Content.ReadAsStringAsync();
return
JsonConvert.DeserializeObject<List<HomeWorkModel>>(apiResponse);
}
else
{
return null;
}
}
}
}
public class HomeworkModel
{
Public bool Result {get; set;}
}
whereas :
"Constants.ApiBaseUrl" is http address for base Url of another API
But in case of the same API you will use old solution :
you can pass "CHeckHomeWorkService" in your controller constructor ("Dependency Injection")
and call service methods as you like

NOT RECIEVING The Datas on GET Method - MVC WEB API

I got a problem that my asp.net mvc solution isn't reading my json, and I need some help with this.
First of all, let me introduce you guys to the problem.
I need just to put a GET METHOD, read some information and that's all.
But, the problem is, when i am using a simple j-son it works. As you guys can see above:
.
https://i.imgur.com/d3DyCiB.jpg "The Postman"
.
https://i.imgur.com/e5b6DYA.jpg "The View showing the data"
.
Here what I'm using on my controller/mycodes
https://i.imgur.com/LEYDDUF.jpg "The Code"
.
https://i.imgur.com/wRjYPet.jpg "The Code2"
.
And here what i really need to receive, but comes null:
.
https://i.imgur.com/mbj5lB8.jpg "The J-Son"
.
https://i.imgur.com/vitUQvr.jpg "Returns null"
-- FindAll Clients:
public class ProductClient
{
private string BASE_URL = "http://localhost:50166/api/Clientes";
public IEnumerable<Cliente> findAll()
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(BASE_URL);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync(BASE_URL).Result;
if (response.IsSuccessStatusCode)
{
return response.Content.ReadAsAsync<IEnumerable<Cliente>>().Result;
}
return null;
}
catch
{
return null;
}
}
}
My Index
public ActionResult Index()
{
ProductClient pc = new ProductClient();
ViewBag.Clientes = pc.findAll();
return View();
}
You have to specify [FromUri] in the method's parameter. Web API expecting it to come from the Request body by default. You can add the [FromUri] like this:
public IEnumerable<string> findAll([FromUri]List<string> stringColumnNames)
{
return Ok(pc.findAll(stringColumnNames));
}
add call like this
http://localhost:59511/api/Values?str[]="abc"&str[]="xyz"

Content Negotiation in ASP.NET Web API

I'm migrating a web service to ASP.NET Web Api 2, and hitting trouble at almost the first hurdle.
I want to do this:
public class SomeController : ApiController
{
[Route("some\url")]
public object Get()
{
return { Message = "Hello" };
}
}
And be able to ask the service for either "application/json" or "application/xml" (or indeed any other potential format, such as Message Pack), and get a serialized response. But it seems it only works for JSON.
I've read this and seen the documentation which states clearly that the framework cannot handle serialization of anonymous types into XML (seriously) and that the solution is to not use XML (seriously).
When I attempt to call this and request XML as response type, I get
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.
I'm not removing support for clients wanting to ask for XML - but I genuinely can't find a work around for this - what can I do?
Edit
I've added these:
System.Web.Http.GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
config.Formatters.Insert(0, new System.Net.Http.Formatting.JsonMediaTypeFormatter());
config.Formatters.Insert(0, new System.Net.Http.Formatting.XmlMediaTypeFormatter());
as per Dalorzo's answer, but it made no difference.
For clarification, the service works absolutely fine when I call it using an accept header of application/json, but bombs when I call it with an accept header of application/xml.
You have 3 options:
Create a class with a proper name and return the object instead of an anonymous type.
Or if you want to return the anonymous instance, you should remove XML formatter, because anonymous types are not supported by XML Formatter
Create your own formatter inheriting from MediaTypeFormatter or BufferedMediaTypeFormatter
You can do it by following code :
public HttpResponseMessage GetTestData()
{
var testdata = (from u in context.TestRepository.Get().ToList()
select
new Message
{
msgText = u.msgText
});
return ActionContext.Request.CreateResponse(HttpStatusCode.OK, testdata);
}
// This Code Is Used To Change Contents In Api
public HttpResponseMessage GetAllcarDetails( string formate)
{
CarModel ST = new CarModel();
CarModel ST1 = new CarModel();
List<CarModel> li = new List<CarModel>();
ST.CarName = "Maruti Waganor";
ST.CarPrice = 400000;
ST.CarModeles = "VXI";
ST.CarColor = "Brown";
ST1.CarName = "Maruti Swift";
ST1.CarPrice = 500000;
ST1.CarModeles = "VXI";
ST1.CarColor = "RED";
li.Add(ST);
li.Add(ST1);
// return li;
this.Request.Headers.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/xml"));
//For Json Use "application/json"
IContentNegotiator negotiator =
this.Configuration.Services.GetContentNegotiator();
ContentNegotiationResult result = negotiator.Negotiate(
typeof(List<CarModel>), this.Request, this.Configuration.Formatters);
if (result == null) {
var response = new HttpResponseMessage(HttpStatusCode.NotAcceptable);
throw new HttpResponseException(response);
}
return new HttpResponseMessage() {
Content = new ObjectContent<List<CarModel>>(
li, // What we are serializing
result.Formatter, // The media formatter
result.MediaType.MediaType // The MIME type
)
};
}
Please browse your API route on Chrome. Chrome, by default shows output in XML format. If that doesn't happen, it means that your service is preventing XML format using media formatting.
And in that case, you should search your WebApiConfig. If nothing is present there, add this file to your project
using System.Net.Http.Formatting;
using System.Collections.Generic;
using System.Net.Http;
using System;
using System.Linq;
using System.Net.Http.Headers;
namespace ExampleApp.Infrastructure
{
public class CustomNegotiator : DefaultContentNegotiator
{
public override ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
{
if(request.Headers.UserAgent.Where(x=>x.Product!=null&& x.Product.Name.ToLower().Equals("chrome")).Count() > 0)
{
return new ContentNegotiationResult(new JsonMediaTypeFormatter(), new MediaTypeHeaderValue("application/xml"));
}
else
{
return base.Negotiate(type, request, formatters);
}
}
}
}
and, in WebApiConfig.cs, add:
config.Services.Replace(typeof(IContentNegotiator), new CustomNegotiator());

How to call a Post api with multiple parameters

How can i call a Post method with multiple parameters using HttpClient?
I am using the following code with a single parameter:
var paymentServicePostClient = new HttpClient();
paymentServicePostClient.BaseAddress =
new Uri(ConfigurationManager.AppSettings["PaymentServiceUri"]);
PaymentReceipt payData = SetPostParameter(card);
var paymentServiceResponse =
paymentServicePostClient.PostAsJsonAsync("api/billpayment/", payData).Result;
I need to add another parameter userid. How can i send the parameter along with the 'postData'?
WebApi POST method prototype:
public int Post(PaymentReceipt paymentReceipt,string userid)
Simply use a view model on your Web Api controller that contains both properties. So instead of:
public HttpresponseMessage Post(PaymentReceipt model, int userid)
{
...
}
use:
public HttpresponseMessage Post(PaymentReceiptViewModel model)
{
...
}
where the PaymentReceiptViewModel will obviously contain the userid property. Then you will be able to call the method normally:
var model = new PaymentReceiptViewModel()
model.PayData = ...
model.UserId = ...
var paymentServiceResponse = paymentServicePostClient
.PostAsJsonAsync("api/billpayment/", model)
.Result;
UserId should be in query string:
var paymentServiceResponse = paymentServicePostClient
.PostAsJsonAsync("api/billpayment?userId=" + userId.ToString(), payData)
.Result;
In my case my existing ViewModels don't line up very nicely with the data I want to post to my WebAPI. So, instead of creating an entire new set of model classes, I posted an anonymous type, and had my Controller accept a dynamic.
var paymentServiceResponse = paymentServicePostClient.PostAsJsonAsync("api/billpayment/", new { payData, userid }).Result;
public int Post([FromBody]dynamic model)
{
PaymentReceipt paymentReceipt = (PaymentReceipt)model.paymentReceipt;
string userid = (string)model.userid;
...
}
(I'd be curious to hear some feedback on this approach. It's definitely a lot less code.)

Categories