.net core not routing to POST method - c#

Link to project here -> https://github.com/crumdev/hqbbq.git
I have a simple 3 page MVC website with 1 controller. For the contact page I have a small 3 input form. Below are the Controller methods:
[Route("contact/")]
public IActionResult Contact()
{
return View();
}
[HttpPost]
public IActionResult Contact(string name, string email, string message)
{
ViewBag.Name = name;
ViewBag.Email = email;
ViewBag.Message = message;
return View();
}
When I submit the form with a breakpoint inside of the Contact method for HttpPost it never breaks but instead uses the regular method and just returns the view again. I have tried reducing my form to just the name field and only capture that and it does not enter the POST method. I have given the regular Contact method the [HttpGet] attribute so it can only be used strictly for GET requests and when I submit the form then it bypasses my controller altogether and returns the Dev exception page that is blank except for "Hello World!" on the screen. I have read through the documentation and followed tutorials on teamtreehouse.com for regular ASP.Net as well but cannot understand why it is behaving this way.
Edit:
Here is the code for the page submitting the POST. I am just using a plain HTML form with the POST method for submitting the data.
https://github.com/crumdev/hqbbq/blob/master/HQ-BBQ/Views/Home/contact.cshtml

The POST action needs to have a route as well if the intention is to use attribute routing.
[HttpGet]
[Route("contact")]
public IActionResult Contact() {
return View();
}
[HttpPost]
[Route("contact")]
public IActionResult Contact(string name, string email, string message) {
ViewBag.Name = name;
ViewBag.Email = email;
ViewBag.Message = message;
return View();
}
Note the exclusion of the slashes as they are not needed. Make sure the names and ids of the form inputs match the parameters of the target action

It looks like you're missing the Route attribute on the [HttpPost] method.
Try this.
[HttpPost]
[Route("contact/")]
public IActionResult Contact(string name, string email, string message)
Also update your view code, so that the name property of your <input /> tags matches the arguments of your controller action.
Remember that MVC uses the name property to bind to the arguments in your controller action. MSDN Model Binding
For example update your email input to include the name property:
<input name="email" id="email" class="input" type="text" placeholder="Email" value="#ViewBag.Email">
You'll also need to update the text area name to name="message".

You can use the FromForm annotation for your parameters in the controller post method
[HttpPost]
[Route("contact")]
public IActionResult Contact([FromForm]string name, [FromForm]string email, [FromForm]string message)
I would also recommend to use a viewmodel rather than passing all the fields of your form as parameters. Imagine you have a form with 10 fields, your method signature would be a way harder to read

I couldn't route to action because i passed object not matched to model, for instance
public class NewsModel : IActive
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public string NewsName { get; set; }
public string NewsText { get; set; }
public bool Active { get; set; }}
{"id":0,"newsName":"123","newsText":"123","active":""}
active - should be boolean, but i passed string.
So first thing one have to do is to remove parameters in Post methods.
[HttpPost] public async Task<IActionResult> PostNews( )
If now you get in action, so you have problem in model, otherwise - you have problem in routing

Related

how do get header that i set in response object

My action method returns a view. It looks like the following.
public public ActionResult Init(string additionalParams)
{
Response.AddHeader("additionalParams", additionalParams);
return View(model);
}
The view has a form. The form is submitted to another action method
[HttpPost]
public ActionResult InitPost(MyModel model)
{
string additionalParams = Request.Headers.Get("additionalParams"); <--- getting null
}
how do i get the additionalParams in the post? Please help.
So on the Init(), I was using Route attribute routing, that makes urls look like this http://wwww.example.com/23/22/... Apparently this caused issues with the length of url. So I switched to using query string, by removing the route attribute routing. Now with this url, I can pass my additionalParams just fine, http://www.example.com?id=222&otherID=222&additionalParams="whatever"

asp.net core Api - insert new row in database

I'm trying to create an address object in a database through an asp.net core api. I'm using Postman to invoke the method.
Class:
namespace LC.Tools.API.Controllers {
[Route("api/[controller]")]
public class MailerController : Controller
{
Data.LCToolsDbContext _context;
public MailerController(Data.LCToolsDbContext context)
{
_context = context;
}
[HttpPost]
public async Task<IActionResult> CreateAddress(int client, string name, string email)
{
Address adr = new Address() { ClientId = client, Name = name, Email = email };
_context.MailerAddresses.Add(adr);
await _context.SaveChangesAsync();
return Ok(adr);
}
} }
URL (using POST):
http://localhost:50444/api/mailer/createAddress?client=1&name=test&email=mail#mail.no
I also have a break point in the method, but it never hits. I don't get any error message, it just doesn't do anything.
You can see #Rick van den Bosch's comment but still you would like to specify the route with action. use this
[Route("api/[controller]/[action]")]
See #Ayvaras' comment. Since you're building a Web API controller, you don't have to specify the action name in your URL. The HttpPost points all POST actions to the mailer controller towards the CreateAddress method.
Your POST URL should be:
http://localhost:50444/api/mailer?client=1&name=test&email=mail#mail.no
Problem solved! Thanks Ayvaras,
[Route("api/[controller]/[action]")]
did the trick. Now that the method is found I can look into how to pass an object instead of using querystring
You are not using POST correctly.
If you use POST you should not be sending parameters through the query string, you should use the request body. Even though, if you still have to send them via query string you should use the FromQuery attribute in your action parameters.
[HttpPost]
public async Task<IActionResult> CreateAddress([FromQuery] int client, [FromQuery] string name, [FromQuery] string email)
{
Address adr = new Address() { ClientId = client, Name = name, Email = email };
_context.MailerAddresses.Add(adr);
await _context.SaveChangesAsync();
return Ok(adr);
}
Edit: Use [Route("api/[controller]/[action]")] to append the action name in your action route.
Instead of changing the controllers routing scheme, it's also possible to specify the endpoint name by doing the following
[HttpPost("createAddress")]
public async Task<IActionResult> CreateAddress(int client, string name, string email)
{
[...]
}

How to fix - The requested resource does not support http method 'POST'

Below is WebAPI action. On googling about the below error:-
The requested resource does not support http method 'POST'
I got number of links & updated my api accordingly but still I am getting the same error.
Web api not supporting POST method
ASP.NET Web Api: The requested resource does not support http method 'GET'
[AcceptVerbs("POST")]
[HttpPost]
[Route("rename/{userId}/{type}/{title}/")]
public IHttpActionResult Rename([FromBody] int userId, [FromBody] string type, [FromBody] string title)
{
//my api stuff
}
But still when calling the above via post man throws the error.
How do I get rid of this error??
Also is it possible to fix this without using [FromBody] attribute in the method parameters list?
Any help/suggestion highly appreciated.
Thanks.
You have declared route which requires url parameters
[Route("rename/{userId}/{type}/{title}/")]
So when you send request to api/customer/rename it does not match this method. You should remove parameters which you are passing in request body from route parameters
[Route("rename")]
Make sure that you have appropriate RoutePrefix("api/customer") attribute on your controller.
Second problem is multiple [FromBody] parameters. You will get can't bind multiple parameters error. There is limitation - you can mark only one parameter as FromBody. See Sending Simple Types notes:
Web API reads the request body at most once, so only one parameter of
an action can come from the request body. If you need to get multiple
values from the request body, define a complex type.
You should create complex type which will hold all parameters
public class RenameModel
{
public int UserId { get; set; }
public string Type { get; set; }
public string Title { get; set; }
}
And change method signature to
[HttpPost]
[Route("rename")]
public IHttpActionResult Rename(RenameModel model)
And send request data as application/x-www-form-urlencoded
[Route("rename/{userId}/{type}/{title}/")]
public IHttpActionResult Rename([FromBody] int userId, [FromBody] string type, [FromBody] string title)
The last answer is correct, you're asking for these parameters in the route, but saying that you expect them in the post body. Also, usually the route would begin with a noun rather than a verb. What is it you're renaming? (i.e. [Route("users/rename/{userId}/{type}/{title}")]
Based on your initial post, try this instead:
[HttpPost]
[Route("rename/{userId}/{type}/{title}" Name = "RenameUser"]
public IHttpActionResult Rename(int userId, string type, string title)
{
_myServiceMethod.Rename(userId, type, title);
return new StatusCodeResult(HttpStatusCode.Created, this);
}
Or, if you wanted to do a post with the info in the body:
Declare your data contract:
public class User
{
public string Type { get; set; }
public string Title { get; set; }
}
Then on the endpoint:
[HttpPost]
[Route("rename/{userId}", Name = "RenameUserPost")]
public IHttpActionResult RenameUserPost(int userId, [FromBody] User userData)
{
return new StatusCodeResult(HttpStatusCode.Created, this);
}
Note that in both returns 'this' refers to your controller class that inherits from ApiController. Verified both of these in swagger, and they accept POSTs and return status codes.
Hope this helps.
I had this error for wrong string in Route string on top of my action.
[Route("api/TestReaderPercentStudyHomework/AddOrUpdate")]

How to pass a value from a controller method to an another?

I'm beginner in MVC3, and I want to get a value from an another controller's method. Here the two methods:
[HttpPost]
public ActionResult Create(TennisClub tennisclub)
{
if (ModelState.IsValid)
{
db.TennisClubs.Add(tennisclub);
db.SaveChanges();
return RedirectToAction("AssignManager");
}
return View(tennisclub);
}
[HttpPost]
public ActionResult AssignManager(Manager manager)
{
}
So, when I'm creating a new tennis club, Immediately I would like to assign a manager to it... For that I need the primary key "ID".
So my question is: How to get this ID in my "AssignManager" method ? Thanks in advance
You cannot redirect to an action decorated with the [HttpPost] attribute. That's not how a redirect works. A redirect means that you are sending a 301 HTTP status code to the client with the new Location header and the client issues a GET request to this new location.
So once you remove the [HttpPost] attribute from your AssignManager action you could pass the id as parameter:
return RedirectToAction("AssignManager", new { id = "123" });
and then:
[HttpPost]
public ActionResult AssignManager(int id)
{
}
Basically, you need to have a GET AssignManager method, too, which would have a parameter telling it to which TennisClub the manager should be assigned:
[HttpGet]
public ActionResult AssignManager(int tennisClubId)
{
// here, you will want to return AssignManager view
}
And when redirecting to AssignManager from Create, you can specify the id of TennisClub:
return RedirectToAction("AssignManager", new { tennisClubId = tennisclub.Id });
return RedirectToAction("AssignManager", new { id = tennisclub.Id });
Also you need to remove the [HttpPost] attribute from your action
public ActionResult AssignManager(int id) {
//...
}

Adjust parameter name in controller action to map HTTP request parameter

I have the problem that I must map a fixed URL parameter that contains an underline (e.g. purchase_id) to an controller.
public ActionResult Index(
long purchase_Id,
That is working, and it's not my problem. The thing that annoys me, is the underline in the parameter name, due to the fact, that I can't change the given URL Parameter. It's called purchase_id
e.g. http://www.example.com/Order?purchase_id=12123
Is there any chance to get the following thing working, without changing the URL parameter?
public ActionResult Index(
long purchaseId,
Thanks for your help.
public ActionResult Index()
{
string purchaseId = Request["purchase_id"];
return View();
}
or:
public ActionResult Index([Bind(Prefix="purchase_id")]string purchaseId)
{
return View();
}

Categories

Resources