Blazor Webassembly - Putting/Posting to API Controller - asp.net-core

I have a controller - roughed out below. And then you see the call I make from the client.
When I make the client call to post, it gives me a Bad Request error.
[ApiController]
[Route("[controller]")]
public class MainController : ControllerBase
{
[HttpPost]
public IActionResult Post(Policies policy)
{
myModelContext.Policies.Update(policy);
myModelContext.SaveChanges();
return Ok();
}
}
//client code
protected async void OnUpdating(GridCommandEventArgs editRow)
{
HttpResponseMessage httpResponseMessage = await httpClient.PostAsJsonAsync($"Main", (Policies)editRow.Item);
if (!httpResponseMessage.IsSuccessStatusCode)
{
toastService.ShowError(httpResponseMessage.ReasonPhrase);
}
}
I've tried everything

Related

Unable to cast object of type 'MyAPI.Api.Middleware.MyFilter' to type 'Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata'

My requirement is to modify the response from the controller before sending it back to the client.
I am trying to implement IActionResult interface.
public class MyFilter: IActionResult
{
ApiResponse _response = new ApiResponse();
public async Task ExecuteResultAsync(ActionContext context)
{
var httpResponse = context.HttpContext.Response;
if (httpResponse != null)
{
if (httpResponse.StatusCode == 200)
{
if (context.Result.GetType().Equals(typeof(Microsoft.AspNetCore.Mvc.ObjectResult)))
{
_response.Response = ((Microsoft.AspNetCore.Mvc.ObjectResult)context.Result).Value;
_response.Errors = null;
_response.IsSuccess = true;
}
}
}
return ;
}
}
my program.cs has
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddSingleton<MyFilter>();
builder.Services.AddAppServices();
builder.Services.AddControllers();
builder.Services.AddDataContext(builder.Configuration);
builder.Services.AddRepositories();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
app.UseRouting();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
my controller has the attribute
[Route("api/[controller]")]
[ApiController]
[ServiceFilter(typeof(MyFilter))]
public class MyController : ControllerBase
{
}
But when I invoke any of the controller action methods it doesn't reach and gives me an exception as response.
is there something I am missing completely?
You should implement IActionFilter or IAsynActionFilter not IActionResult!
To create an Acton filter, we need to create a class that inherits either from the IActionFilter interface or IAsyncActionFilter interface or from the ActionFilterAttribute class which is the implementation of the IActionFilter, IAsyncActionFilter, and a few different interfaces as well:
public abstract class ActionFilterAttribute : Attribute, IActionFilter, IFilterMetadata,
IAsyncActionFilter, IResultFilter, IAsyncResultFilter, IOrderedFilter
for example:
namespace ActionFilters.Filters
{
public class ActionFilterExample : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
// our code before action executes
}
public void OnActionExecuted(ActionExecutedContext context)
{
// our code after action executes
}
}
}
then on your startup.cs (or program.cs in .net 6 and above):
builder.Services.AddScoped<ActionFilterExample>();
Finally, to use a filter registered on the Action or Controller level, we need to place it on top of the Controller or Action as a ServiceType:
namespace AspNetCore.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
[HttpGet]
[ServiceFilter(typeof(ActionFilterExample))]
public IEnumerable<string> Get()
{
return new string[] { "example", "data" };
}
}
}
read more: codeMaze microsoft docs

Catch and repsonse custom json on 405 HTTP error - ASP.NET CORE API

I am trying to capture error 405 to launch a personalized response, but I can not do it. When I make a call to the method, I get a generic error of CORS problem
//Startup.cs
servicesCollection.AddCors(x =>
{
x.AddPolicy(CORS.AllowPutMethod,
policyBuilder =>
{
policyBuilder.WithOrigins("http://localhost:4200")
.WithMethods(HttpMethods.Put).AllowAnyHeader();
});
x.AddPolicy(CORS.AllowPostMethod,
policyBuilder =>
{
policyBuilder.WithOrigins("http://localhost:4200")
.WithMethods(HttpMethods.Post).AllowAnyHeader();
});
});
public static class CORS
{
public const string AllowPutMethod = nameof(AllowPutMethod);
public const string AllowPostMethod = nameof(AllowPostMethod);
}
[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
// PUT: api/User/5
[HttpPut("{id}")]
[EnableCors(CORS.AllowPostMethod)] <=== ERROR HERE!!!
public void Put(int id, UserDTO currentUser)
{
}
}
You shoul use CORS.AllowPutMethod instead of CORS.AllowPostMethod on the Put method.
[HttpPut("{id}")]
[EnableCors(CORS.AllowPutMethod)]
public void Put(int id, UserDTO currentUser)
{
}

.Net Core 2.0 Web API controller not working and getting 404

I have something very very strange. I have 2 controllers. UploadController and AccountController. Theye were both working, and now when I try the AccountController it give error 404. ik don't get it.
This is how my AccountController looks like:
namespace CoreAngular.Controllers
{
//[Authorize]
[Produces("application/json")]
[Route("api/account")]
public class AccountController : Controller
{
private IRepository repository;
public AccountController(IDatabaseClient<DocumentClient> client)
: this ( new UserRepository(client))
{
}
public AccountController(IRepository repository)
{
this.repository = repository;
}
[HttpGet]
public async Task<ActionResult> Get(string id)
{
var start = DateTime.Now.TimeOfDay;
if (string.IsNullOrEmpty(id))
{
return BadRequest();
}
var user = await repository.GetAsync(id);
if (user == null)
{
return NotFound();
}
var userDTO = new UserGetDTO()
{
image = Convert.ToBase64String(user.image.image),
id = user.id,
time = DateTime.Now.Subtract(start).Millisecond
};
return Ok(userDTO);
}......
Do I miss something here? I know I comentet out the [Authorize], but i just wanted to try to connect.
You should specify route template in HttpGet attribute:
[HttpGet("{id}")]
public async Task<ActionResult> Get(string id)
{
// ...
}

ASP.NET Core: Many routes -> always only one controller

Similar to SO ASP.NET MVC: Many routes -> always only one controller:
O have a .net 4.7 MVC project project
my config route are as follows (following from the above post)
config.Routes.MapHttpRoute(
name: "AllRoutes",
routeTemplate: "{*url}",
defaults: new
{
controller = "base",
});
my base controller in my .net 4.7 project
public class BaseController : ApiController
{
[HttpGet]
public IHttpActionResult Get(HttpRequestMessage request)
{
return Ok();
}
[HttpPost]
public IHttpActionResult Post(HttpRequestMessage request)
{
return Ok();
}
[HttpPut]
public IHttpActionResult Put(HttpRequestMessage request)
{
return Ok();
}
[HttpDelete]
public IHttpActionResult Delete(HttpRequestMessage request)
{
return Ok();
}
}
now I'm porting my project into a .NET Core 2.0
I can't seem to setup the same thing
my config in the .net core project is as follows
app.UseMvc(routes =>
{
routes.MapRoute(
name: "AllRoutes",
template: "{*url}",
defaults: new
{
controller = "Base"
}
);
my base controller for my .net core project
//[Route("api/[controller]")]
public class BaseController : Controller
{
[HttpGet]
public IActionResult Get()
{
return Ok("get success");
}
// POST api/values
[HttpPost]
public IActionResult Post([FromBody]string value)
{
return Ok("post success");
}
[HttpPut]
public IActionResult Put([FromBody]string value)
{
return Ok("put success");
}
[HttpDelete]
public IActionResult Delete()
{
return Ok("delete success");
}
}
any ideas?
Why do you even want to use MVC, when you have no controllers or routes?
Just use a custom middleware:
// Startup configure
app.Use(async (context, next) =>
{
var service = context.RequestServices.GetRequiredServce<MyService>();
var service.Execute();
async next();
});
Update
Just in case it's not clear, you can inject IHttpContextAccessor in your service, where you can directly access the request stream and do whatever you need to do with it.
public class BaseContoller : Controller {
[HttpGet("/base/get")]
public IActionResult Get() {
return Ok("get success");
}
[HttpPost("/base/post")]
public IActionResult Post() {
return Ok("post success");
}
}
you looking for something like this?
or if you want to route this links you need add something like this
public class BaseController : Controller {
[Route("/get")]
public IActionResult Get() {
return Ok("get success");
}
}

WebApi for Email delivery

I created a Web API controller inside my ASP.NET MVC 4 Website to specifically send emails so that I can consume it for this purpose and eventually provide it to other consumers (Mobile, etc).
Everything is working fine but I want to use it asynchronously, altough it's not working that way, my website blocks until the work is finished.
I have a regular Controller where I call a helper class that calls the API.
Controller Code :
[HttpPost]
public async Task<ActionResult> ContactUs(ContactUsModel model)
{
ExternalApiCalls extApi = new ExternalApiCalls();
await extApi.PostContactUs(model).ConfigureAwait(false);
return RedirectToAction("ContactUsSuccess", "Account");
}
Helper Class Code :
public class ExternalApiCalls
{
public HttpClient client { get; set; }
public ExternalApiCalls()
{
client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:10239/");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task PostContactUs(ContactUsModel model)
{
try
{
var response = await client.PostAsJsonAsync("api/WAPIMail", model).ConfigureAwait(false);
}
catch (HttpRequestException ex)
{
}
catch (System.FormatException)
{
}
finally
{
}
}
}
Web API Controller :
public class WAPIMailController : ApiController
{
public void PostContactUs(ContactUsModel model)
{
// Send Email Here
}
}
Thanks a lot for your help
I finally managed how to do it..
For brevity's sake, I am showing oversimplified code, see below:
Controller :
[HttpPost]
public ActionResult ContactUs(ContactUsModel model)
{
new ExternalApiCalls().MailContactUs(model);
return RedirectToAction("ContactUsSuccess", "Account");
}
Helper Class :
public void MailContactUs(ContactUsModel model)
{
client.PostAsJsonAsync("api/WAPIMail/MailContactUs", model).ConfigureAwait(false);
}
Web API Controller :
[HttpPost]
public void MailContactUs(ContactUsModel model)
{
//Email Logic Here
}