ASP.NET Core Invoke API via Postman - c#

So i have this ASP.NET Core on my local machine, i have installed the prerequisites and after running the application locally, the response was correct from the web browset that it was not found.
Okay, i am trying to invoked this API via Postman and i couldnt determine why i cant access it though i already checked the routings.
Below is the sample template
[HttpGet]
[Route("Details")]
public async Task<IActionResult> GetDetails(string value = null)
{
var response = new ListModelResponse<SomeModel>() as IListModelResponse<SomeModel>;
try
{
response.Model = await GetDetailsRepository
.GetDetailsSS(value)
.Select(item => item.ToViewModel())
.OrderBy(item => item.Name)
.ToListAsync();
}
catch (Exception ex)
{
response.DidError = true;
response.ErrorMessage = ex.Message;
}
return response.ToHttpResponse();
}
And in application insights of visual studio, i can see that it is invoking the API but it seems it can't get through.
Check this insights snippet
Other API's are working fine, it seems that i am missed something that i can't figure out right now.
For the routing i have this.
[Route("api/[controller]")]
I have also checked the Token and as i parsed it, i am getting the required info to access this API.
Thanks Lads!

It doesn't seem that you have the name of the controller in the request url.
api/[controller]/Details?value=CAT...

This error is due to the incorrect url present in the request. The correct URL has to be https://localhost:44309/api/your-controller-name/Details?value=CAT
ie. If the Controller name is ProductsController, then the URL has to be https://localhost:44309/api/Products/Details?value=CAT.
[Route("api/[controller]")]
public class ProductsController : Controller
{
[HttpPost("Details")]
public async Task<IActionResult> GetDetails(string value = null)
{
...
}
}

Related

Trying to setup web hook for stripe using ASP.NET MVC and C#

I have implemented some front end code which when a user clicks the checkout button they are redirected to a stripe page where they can input their card payment details. the code has a successful URL and failed URL. if the customer enter valid payment details - they are redirected to the successful URL, i need to update my database to ensure that my backend knows that this specific user has paid and can now view subscribed content. I am trying to setup web hooks in order to do this, so I know if the user has paid, cancelled etc.
using System;
using System.IO;
using Microsoft.AspNetCore.Mvc;
using Stripe;
namespace workspace.Controllers
{
[Route("api/[controller]")]
public class StripeWebHook : Controller
{
// You can find your endpoint's secret in your webhook settings
const string secret = "whsec_...";
[HttpPost]
public async Task<IActionResult> Index()
{
var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
try
{
var stripeEvent = EventUtility.ConstructEvent(json,
Request.Headers["Stripe-Signature"], secret);
// Handle the checkout.session.completed event
if (stripeEvent.Type == Events.CheckoutSessionCompleted)
{
var session = stripeEvent.Data.Object as Checkout.Session;
// Fulfill the purchase...
HandleCheckoutSession(session);
}
else
{
return Ok()
}
}
catch (StripeException e)
{
return BadRequest();
}
}
}
}
However when trying to implement this I get errors because I think the custom code provided above uses .NET Core and I am using the full .NET framework.
Is there a way around this or what am I doing wrong?
This may help someone so I'm posting even although it's a bit late to the table as I couldn't find a relevant answer anywhere.
I had this same issue on a dotNet Core MVC web application (so not an exact answer for the question which is .Net Framework) where the Stripe Webhook was constantly giving a 400 Bad Request response. I just couldn't hit it no matter what I tried.
Eventually, and probably obviously the solution for me was to add the [IgnoreAntiforgeryToken] attribute to the Index() method as you have in your question above. As .dotNet Core enables the Validation Token on forms I had to explicitly ignore it. The Webhooks worked as soon as I did that.
So the solution for me was:
[HttpPost]
[IgnoreAntiforgeryToken]
public async Task<IActionResult> Index()
This apparently applies to dot Net Core versions: see Microsofts Documentation
Hope this helps someone.
That's works in my Asp.net Framework 4.7, try below code for the webhook
[HttpPost]
[Route("api/[controller]/webhook")]
public async Task<HttpResponseMessage> ProcessRequest()
{
var json = await new StreamReader(HttpContext.Current.Request.InputStream).ReadToEndAsync();
try
{
var stripeEvent = EventUtility.ParseEvent(json);
// Handle the event
if (stripeEvent.Type == Events.PaymentIntentSucceeded)
{
var paymentIntent = stripeEvent.Data.Object as PaymentIntent;
// Then define and call a method to handle the successful payment intent.
// handlePaymentIntentSucceeded(paymentIntent);
}
else if (stripeEvent.Type == Events.PaymentMethodAttached)
{
var paymentMethod = stripeEvent.Data.Object as PaymentMethod;
// Then define and call a method to handle the successful attachment of a PaymentMethod.
// handlePaymentMethodAttached(paymentMethod);
}
// ... handle other event types
else
{
// Unexpected event type
Console.WriteLine("Unhandled event type: {0}", stripeEvent.Type);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (StripeException e)
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
//Modification and Saving Data
}
After adding this webhook , you can test on locally from https://stripe.com/docs/webhooks/test this link

asp.net mvc 401 Unauthorized error after redirect

I'm getting the 401 Unauthorized error after user is redirected.
User is being redirected to another page after a new user created.
public ActionResult SaveUser(UserViewModel userViewModel)
{
ModelState.Remove("IsDSA");
ModelState.Remove("IsAccountRepresentative");
var savedUser = SaveOrUpdateUser(ref userViewModel);
TempData["Status"] = ViewBag.Status;
TempData.Keep("Status");
var MenuId = Request.QueryString["MenuID"];
TempData["MenuId"] = MenuId;
TempData.Keep("MenuId");
if (userViewModel.AddAnotherUserRequseted && savedUser != null)
{
return RedirectToAction("CreateNewUser", new { MenuID = Request.QueryString["MenuID"] });
}
return RedirectToAction("UserAccessManagement", "UserAccessManagement", new { MenuID = Request.QueryString["MenuID"] });
}
public ActionResult UserAccessManagement(string TabName, long MenuID)
{
...
}
How can I fix this error? Maybe the reason is that authentication cookies are not sent with the redirect?
It is because you forget Authorize attribute on controller
[Authorize]
public class UserAccessManagement: Controller {
public ActionResult Index() {
return View();
}
}
So after a full day of investigation I started to doubt that reason may be in the Authorize Attribute or global filters and began thinking that maybe IIS somehow returns 401 on the redirect requests. But some of other actions with RedirectToAction were found by me and they worked. Besides versions hosted on another IIS had the same problem
Then I started to wonder if there is any Authorization configuration in the MVC project other then default and searched through the project "authorize" which didn't give any unexpected results
But then an idea came up to me to search through all the solution the "redirect" phrase and I finally found the root of the issue...
So on the Application_EndRequest the StatusCode is set to 401 and the error returned for the wrong type of the request
I guess searching for "401" would also help and if the constants were named they would have been found earlier

Not able to fetch response from HttpClient POST method using Angular 7, .net core 2.2

I am creating quite basic implementation of CRUD methods using Angular and ASP.NET Core in the back end.
The back-end work perfectly, but cannot get the response after redirect action.
Let me bring the code:
the C# Controller bit:
[HttpPost]
[ProducesResponseType(200, Type = typeof(IActionResult))]
public async Task<ActionResult<CapCustomerResponseDto>> CreateCustomer([FromBody] CreateCustomerRequestDto request)
{
try
{
///. .. *creating command*
await _createCustomercommandHandler.Execute(command);
return CreatedAtRoute("GetCapCustomer", new { id = command.Id.ToString() }, command);
}
catch (Exception e)
{
// Some custom handling
}
}
So at the end we have the magical CreatedAtRoute() method, which redirects to the get controller
the Angular 7 httpClient implementation
addCustomer(customer): Observable<Customer> {
return this.http.post<Customer>(apiUrl, customer, httpOptions).pipe(
tap((customer: Customer) =>
console.log(`added customer w/ id=${customer.customerId}`)
),
catchError(this.handleError<Customer>("addCustomer"))
);
}
which actually returns nothing.
My customer is added properly, I can see it in the database. When using swagger, I can see the controllers working. Even in Network monitor.
but I have no clue how to retrieve the newly created customer response into my TS classes
Instead I get this:
Error: The requested path contains undefined segment at index 1
from Console
Question.
How can I make this work?

Azure Custom Controller / API .Net backend

I have had a MobileService running on Azure, and have decided to create a new service and migrate the code myself. The new service is of the new type called: Azure Mobile App Service.
Currently I have Authentication working, and can do migrations/update-database. I am following the TodoItem example. I now want to create my own Custom API, which easily worked on MobileService, but I cannot get it working on Azure Mobile App :/
I have followed these two links web-Api-routing and app-service-mobile-backend. And I now have the following:
I have created a new controller:
[MobileAppController]
public class TestController : ApiController
{
// GET api/Test
[Route("api/Test/completeAll")]
[HttpPost]
public async Task<ihttpactionresult> completeAll(string info)
{
return Ok(info + info + info);
}
}
In the mobileApp.cs I have added the below code according to backend:
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
Additionally I have installed the below package according to web-api-routing:
Microsoft.AspNet.WebApi.WebHost
and the call from the client:
string t = await App.MobileService.InvokeApiAsync<string,string>("Test/completeAll", "hej");
Debug shows, that it is the correct URL:
{Method: POST, RequestUri: 'https://xxxxxxx.azurewebsites.net/api/Test/completeAll',
Version: 1.1, Content: System.Net.Http.StringContent, Headers:{ X-ZUMO-FEATURES:
AT X-ZUMO-INSTALLATION-ID: e9b359df-d15e-4119-a4ad-afe3031d8cd5 X-ZUMO-AUTH:
xxxxxxxxxxx Accept: application/json User-Agent:
ZUMO/2.0 User-Agent: (lang=Managed; os=Windows Store; os_version=--; arch=Neutral; version=2.0.31125.0)
X-ZUMO-VERSION: ZUMO/2.0 (lang=Managed; os=Windows Store; os_version=--; arch=Neutral; version=2.0.31125.0)
ZUMO-API-VERSION: 2.0.0 Content-Type: application/json; charset=utf-8 Content-Length: 3}}
But keep getting: 404 (Not Found)
Debug Message "The request could not be completed. (Not Found)"
What am I missing :/ ?
Update
I have tried expanding the code in The mobileApp.cs, with:
HttpConfiguration config = new HttpConfiguration();
new MobileAppConfiguration()
.UseDefaultConfiguration().MapApiControllers()
.ApplyTo(config);
config.MapHttpAttributeRoutes();
app.UseWebApi(config);
based on app-service-backend, however still no access :/
Update
I used fiddler2 to access the endpoint through a browser and got the following results:
Update Again
I have tried to create another minimal solution, but still get the same error. Are there any great tutorials that I can follow to achieve this functionality?
The positive feeling is slowly evaporating . . .
The question is also running now on msdn, I will update here if any information is shown there.
Update
Tested Lindas comment, and I can in fact access the value converter:
// Use the MobileAppController attribute for each ApiController you want to use
// from your mobile clients
[MobileAppController]
public class ValuesController : ApiController
{
// GET api/values
public string Get()
{
MobileAppSettingsDictionary settings = this.Configuration.GetMobileAppSettingsProvider().GetMobileAppSettings();
ITraceWriter traceWriter = this.Configuration.Services.GetTraceWriter();
string host = settings.HostName ?? "localhost";
string greeting = "Hello from " + host;
traceWriter.Info(greeting);
return greeting;
}
// POST api/values
public string Post()
{
return "Hello World!";
}
}
This I access using the both the post and get function:
string t = await App.MobileService.InvokeApiAsync<string, string>("values", null, HttpMethod.Post, null);
or
string t = await App.MobileService.InvokeApiAsync<string, string>("values", null, HttpMethod.Get, null);
But the code I pasted has no route so why can I access it using values? What would the path be to the original controller if did not use the route parameter?
Extra Information
I have now created a support ticket with Microsoft and will update with additional information. . . Hopefully.
Update
Info from MSDN Forum: try MS_SkipVersionCheck
Reading about the attribute here, it does not seem applicable. But I tried it. Still Not Found for my API but the original one is still working. So it did not have an impact on this issue.
Yes !!!
So I finally got it working, I copied the usings from lidydonna - msft git and read about .net backend for mobileservice.
This ended with the following:
using System.Web.Http;
using Microsoft.Azure.Mobile.Server.Config;
using System.Threading.Tasks;
using System.Web.Http.Tracing;
using Microsoft.Azure.Mobile.Server;
namespace BCMobileAppService.Controllers
{
[MobileAppController]
public class TestController : ApiController
{
// GET api/Test
[HttpGet, Route("api/Test/completeAll")]
public string Get()
{
MobileAppSettingsDictionary settings = this.Configuration.GetMobileAppSettingsProvider().GetMobileAppSettings();
ITraceWriter traceWriter = this.Configuration.Services.GetTraceWriter();
string host = settings.HostName ?? "localhost";
string greeting = "Hello from " + host;
traceWriter.Info(greeting);
return greeting;
}
// POST api/values
[HttpPost, Route("api/Test/completeAll")]
public string Post(string hej)
{
string retVal = "Hello World!" + hej;
return retVal;
}
}
}
This is a new controller and not the one that comes with it as lidydonna used. It seemed like it wants both functions get and post. This resulted in the API was registered and could be accessed. This means the client call to the server I used was:
t = await App.MobileService.InvokeApiAsync<string, string>("Test/completeAll", null, HttpMethod.Post, new Dictionary<string, string>() { { "hej", " AWESOME !" }});
dialog = new MessageDialog(t);
dialog.Commands.Add(new UICommand("OK"));
await dialog.ShowAsync();
AND I GOT A RESPONSE YAY!!
Extra Information
The controllers that you create, i.e. the class needs to end with Controller, you can have text before but not after. This information was given on a MSDN forum discussion.
If the post and the get has the same input the server returns Not found. Having different inputs solves the issue.
In case of weird Internal Server Error, i.e. weird you can step through the entire server code all variables that you want to return are initialized, but the client receives the error. Then refer to Internal Server Error - Azure App Service Custom Controller where simple fix to the configuration can solve the issue.
You must have something wrong in your project configuration. I have a working sample here: https://gist.github.com/lindydonna/6fca7f689ee72ac9cd20
After creating the HttpConfiguration object, call config.MapHttpAttributeRoutes(). I added the route attribute [Route("api/Test/completeAll")] and I can confirm that the route is registered correctly.
Try adding this attribute to the ValuesController and check the route.
I found another cause for the 404 errors when it came to use attribute routing.
The code above originally had this in mobileApp.cs:
HttpConfiguration config = new HttpConfiguration();
new MobileAppConfiguration()
.UseDefaultConfiguration().MapApiControllers()
.ApplyTo(config);
config.MapHttpAttributeRoutes();
app.UseWebApi(config);
The config.MapHttpAttributeRoutes() needs to be moved above the .ApplyTo:
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
new MobileAppConfiguration()
.UseDefaultConfiguration().MapApiControllers()
.ApplyTo(config);
Try switching inheriting from ApiController to TableController.
It is really strange but simple API request is not working in azure app service
So I have figure out solution which has worked for me. I have tested http requests with c# http post/get, android post/get, and objective C post/get
So first of all you need to update your Startup.MobileApp.cs class :
new MobileAppConfiguration()
.UseDefaultConfiguration()
.MapApiControllers() /* /api endpoints **missing part***/
.ApplyTo(config);
Then create Azure Mobile App Custom Controller. After that modify little bit your controller to get proper json response
public class Mes
{
public string message { get; set; }
}
// GET api/My
public Mes Get()
{
return new Mes { message = "thanks" };
// return "Hello from custom controller!";
}
// POST api/My
public Mes Post(Mes chal)
{
return new Mes { message = chal.message + "asnwer" };
// return "Hello from custom controller!";
}
}
You can simple leave first variant and get response, but OBjective C will say to you that JSON text did not start with array or object and option to allow fragments...and so on.. This happens because you getting simple string not object. So that is why I have modified my response with class Mes
But it is also depends how you make request and what type of object you expect.
So .MapApiControllers() it is the main key for API and WEB API controller is now changed to azure custom controller.
Hope this helps.

MVC5 app doesn't hit my WebAPI2 POST method for creating new records

I have an MVC5 application, ASP.NET, that, when creating a new record and clicking submit, it calls my WebAPI (version 2 - the new one) to insert the record into the database. Problem is, it's not hitting the POST method in my WebAPI. Anyways, here's my MVC5, front end application code for "Create":
[HttpPost]
public ActionResult Create(BulletinBoard bulletinBoard)
{
bulletinBoard.CreatedDate = DateTime.Now;
bulletinBoard.CreatedBy = HttpContext.User.Identity.Name;
response = client.PostAsJsonAsync("api/bulletinboard", bulletinBoard).Result;
if (response.IsSuccessStatusCode)
{
return View("Index");
}
else
{
LoggerHelper.GetLogger().InsertError(new Exception(string.Format(
"Cannot create a new feedback record due to HTTP Response Status Code not being successful: {0}", response.StatusCode)));
return View("Problem");
}
}
I already defined "client" in my constructor and gave it the base URL for my WebAPI - keep in mind that GET works - so it's not a problem with my URL. I can also manually go to my WebAPI URL and get data back in my browser.
Here's my WebAPI code:
// POST api/bulletinboard
public HttpResponseMessage PostBulletinBoard(BulletinBoard bulletinBoard)
{
if (ModelState.IsValid)
{
db.BulletinBoards.Add(bulletinBoard);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, bulletinBoard);
return response;
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
This worked when I was using WebAPI version 1 which had a different naming convention for the GET and POST and PUT methods.
So, when the URL for the POST request is called (the line that's response = client.PostAsJsonAsync...), the request never hits my POST method in my WebAPI and consequently, no records are inserted into my database. What am I doing wrong?
According to the comments it appears that you have POSTed invalid data (according to the validation rules you defined in your BulletinBoard model) and this validation simply fails. So to fix the issue make sure you are sending valid data.
I think there might be a few reasons why it doesn't hit your post method. Here is my example of Post method. The things you should note is method name and FromBody attribute
public async Task<HttpResponseMessage> Post([FromBody]FoodProduct foodProduct)
{
UnitOfWork.FoodRepository.Edit(foodProduct);
await UnitOfWork.SaveAsync();
return Request.CreateResponse(HttpStatusCode.OK);
}
I also like to use this new RoutePrefix Attribute on my controller, it works perfectly and looks good.
[RoutePrefix("api/Food")]
public class FoodController : BaseApiController
{
///some code here
}

Categories

Resources