I have an model class that is used to validate some user input.
I have an controller with the following.
public IActionResult Checkout(GiftCard giftCard)
{
}
I was wondering how I could on an different action redirect it back to it such as
public IActionResult Preview(GiftCard giftCard)
{
return RedirectToAction("Checkout");
}
The above doesn't work because asp.net is trying to find an action without the model like the one below
public IActionResult Checkout()
{
}
if your url going to be really long make a shorturl so load that and redirect from there, if you use ajax it wont be visible
You could use action with another name and apply action selector to your renamed method. Like next:
[ActionName("Checkout")]
[HttpPost] //Recomend you send user input via post
[ValidateAntiForgeryToken] // and use validation token
public IActionResult CheckoutConfirmed(GiftCard giftCard)
{
//your code
}
public IActionResult Checkout()
{
//your code
}
Check out more about ASP.NET MVC - Selectors
If you need more information about ValidateAntiForgeryToken, you could find it there - Chapter 12: Security
And also, you could find great article about posting there - ASP.NET MVC Preview 5 and Form Posting Scenarios
RedirectToAction has a second parameter called routeValues with which you can pass the GiftCard like following.
public IActionResult Preview(GiftCard giftCard)
{
return RedirectToAction("Checkout", giftCard);
}
Related
I am working on Asp.Net MVC application where I don't want to display define action name in url. So I am applying ActionName with Action in controllers. But when I am defining ActionName with Action then it's not working and showing error page of 404 - not found. So please can you guide me to resolve this issue ?
public ActionResult Login()
{
//code
}
when I am passing url like domain/Login then it's working properly.
[ActionName("SignIn")]
public ActionResult Login()
{
//Code
}
but when I am applying ActionName like above then it's showing error page of 404.
I check about this issue on google but not any work for me.
While returning from the controller , for the same controller you have to specify like
return View("Login");
If you are redirecting to another controller action
return RedirectToAction("ActionName", "ControllerName");
and if you are using javascript to navigate for this action,use like
window.location.href="/ControllerName/SignIn";
Try
[ActionName("SignIn")]
public ActionResult Login()
{
//Code
return View("Login");
}
I work with ASP .NET core, and I have issues.
I have 3 pages which can be created in one controller, but for this pages I must have just one controller and in this conroler, I must have a function which will create separate URL for this 3 pages.
For example:
*http://mydomain/page/*Home, Load, Blog;
For this, I need have navigation, but I will have the same HTML file only will data change from the model.
So I will have 3 navigation button which will navigate user for same page but another content which I will receive from the model, and from controller I just need change page URL.
How I can do this?
You don't want to repeat the HTML? Use one view. And then you can have a controller like this snippet:
class PagesController : Controller
{
[HttpGet("about")]
public IActionResult About() => View("MyCommonView", yourModel); // get the model from wherever you plan to
[HttpGet("contact")]
public IActionResult Contact() => View("MyCommonView", yourModel);
[HttpGet("whateverelse")]
public IActionResult WhateverElse() => View("MyCommonView", yourModel);
}
It's possible to just have one action, but I wouldn't do that. I'd instead have separate views per action, and put the markup that's common for the three actions layout file. That will give the different actions more flexibility.
One of the way is to decorate your action with Route attribute:
[Route("page")]
public class PagesController : Controller
{
// you may also use [HttpGet("{pageName}", Name = "PagePath")] instead,
// to explicitly match HTTP GET requests
[Route("{pageName}", Name = "PagePath")]
public IActionResult GetPage(string pageName)
{
switch(pageName?.ToLower())
{
case "home":
return View("Page", homeModel);
case "home":
return View("Load", loadModel);
case "home":
return View("Blog", blogModel);
default:
return NotFound();
}
}
}
Now you can create your view at Views/Pages/Page.cshtml and generate links with helpers:
#Url.RouteUrl("PagePath", new { pageName = "Home" }) <!-- will produce "/page/Home" string -->
I am trying to pass a textbox's text back to a method in my controller, but the data is not being passed in the parameter
I am genuinely confused, i'm following another example but i'm getting a different result, ie - my method behaving as if no parameter is passed
Code
public ActionResult Index(string searchString)
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
var listOfAnimals = db.Animals.ToList();
if (!String.IsNullOrEmpty(searchString))
{
listOfAnimals = listOfAnimals.Where(a => a.AnimalName.ToLower().Contains(searchString.ToLower())).ToList();
}
return View(listOfAnimals);
}
and here is my razor form from my view page
#using(Html.BeginForm("Index", "Home"))
{
#Html.TextBox("searchString")
<input type="submit" id="Index" value="Index" />
}
Can anybody spot why this isn't working?
If more code is needed, please let me know but i think the issue is isolated to here
You code is correct.
Since you didn't add [HttpGet] or [HttpPost] before index method.
This method was called twice.
The first call ran when producing the page with form via url http://server/Home/Index. This call was an http get and searchString mapped from URL was null, which is correct.
The second call ran when you clicked submit button. Correct value would be mapped by MVC correctly.
You need to have 2 Index actions (two methods), one without decorations (GET verb) and another one decorated with HttpPost (POST verb). Basically, when you go to the index page, the GET action is executed. When you submit the form, a POST request is executed and the Index decorated with HttpPost is executed.
// GET
public ActionResult Index() { ... }
// POST
[HttpPost]
public ActionResult Index(string searchString) { ... }
Francisco Goldenstein wrote the recommended way. It means you can have two Index() actions:
// for GET
public ActionResult Index() { ... }
// for POST
[HttpPost]
public ActionResult Index(string searchString) { ... }
However it is possible to have one Index() method for handling both (GET and POST) requests:
public ActionResult Index(string searchString = "")
{
if(!string.IsNullOrEmpty(searchString)
{ /* apply filter rule here */ }
}
You wrote, your code is not working. Do you mean, your action method is not requested after click on the button? Consider to allow empty value Index(string searchString = "")
If your action method is fired but variable is empty, check the name on the View() side. Textbox must not be disabled, of course.
I am fairly new to MVC and i'm looking for advice on how to setup a particular registration controller.
I have a controller called AccountController which has a Register method and I have a Register.cshtml.
Now, one of the biggest problems I seem stuck on is that I have 2 dropdowns that I need to populate based on the response from a service as these values change depending on location and other various parameters.
I have my page started and loading but I'm not sure what to do once a user click 'register'.
#model Adw.Models.RegisterModel //This is my model
#Html.DropDownListFor(m => m.States, new SelectList(Model.States)); // I load my dropdowns here
[AllowAnonymous]
public ActionResult Register(RegisterModel model)
{
model.States = Services.GetStates().Payload;
model.Countries = Services.GetCountries().Payload;
return View(model);
}
So my question is, when a user submits the form, should it come back to this same method? If so what would be the best way to validate that this is a submit rather than an initial load?
Also i haven't done much in the way of error handling and could use a suggestion on that, such as if either of the above service calls fail, then a registration cannot be completed, should that direct to a new page or is there a easy way to build that kind of error into the same page?
You should create two different method. One for GET and second for POST request:
[AllowAnonymous]
[HttpGet]
public ActionResult Register()
{
...
}
[AllowAnonymous]
[HttpPost]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// create user
return this.RedirectToAction("SignIn");
}
else
{
return View(model);
}
}
You can review sample from default template.
I'm writing my app using Asp.Net MVC 3. In my controller I have two action methods with the very same code apart from one line. Here it is:
[HttpPost]
public ActionResult EditPost(Post post)
{
if (ModelState.IsValid)
{
_postsRepository.UpdatePost(post);
return RedirectToAction("NewsFeed");
}
return View("EditPost", post);
}
[HttpPost]
public ActionResult AddPost(Post post)
{
if (ModelState.IsValid)
{
_postsRepository.UpdatePost(post);
return RedirectToAction("NewsFeed");
}
return View("AddPost", post); // the return view is different
}
So, I want to withdraw all this code into helper method.
What I've already tried:
1) I tried to put all the code into helper method and pass as parameters ModelState.IsValid and View name. And then in AddPost and EditPost I call this helper method instead of code listed above. Here is the new code:
[HttpPost] // also tried without this attribute
public ActionResult HelperPost(Post post, string viewName, bool modelState)
{
if (modelState)
{
_postsRepository.UpdatePost(post);
return RedirectToAction("NewsFeed");
}
return View(viewName, post);
}
[HttpPost] // also tried without this attribute
public void AddPost(Post post)
{
HelperPost(post, "AddPost", ModelState.IsValid);
}
The EditPost code is almost the same. The view name is "EditPost".
When I run the app and AddPost method executes the validation works and the new post is created but this line never executes:
return RedirectToAction("NewsFeed");
So I'm redirected to "AddPost" view again and again.
2) Also tried to redirect to HelperPost method instead of calling it withing AddPost and EditPost. The result is still the same: seems like RedirectToAction("NewsFeed") doesn't execute. (Here I neglected the validation just to simplify the example, cause I would have to create new model with properties: Post post, string viewName, bool modelState). The code:
[HttpPost] // tried without attribute
public void AddPost(Post post)
{
return RedirectToAction("HelperPost", post);
}
[HttpPost] // tried without attribute
public RedirectToRouteResult HelperUpdatePost(Post post)
{
_postsRepository.UpdatePost(post);
return RedirectToAction("NewsFeed");
}
So, How could I refactor my code so my action methods (EditPost and AddPost) would not contain the same chunk of code?
p.s. I need different views for AddPost and EditPost methods cause the "back to content" links in them are different. So, I can't just redirect to the EditPost view from AddPost method.
Thanks for help in advance!
Just put your "back to content" link in the model, then use the same view for both, then you can use the same HttpPost method. Saves having to duplicate everything.
I would solve it like this:
I would withdraw the method implementation into separate private
method. This method will be invoked by each of the public action
methods. Since the View name differs for both methods I would pass
the view name as parameter to the private method.
The private method doesn't need the HttpPostAttribute!
Don't forget to declare Add and Edit action methods as returning
ActionResult! As parameter they will expect only Post, the view name has to be hard-coded into the action methodsiteslf ;-)
I hope this helps.