Multiple Models in a single View: submit failure - c#

I'm new to MVC C# and I'm still learning the basics.
I was doing the guide at the link http://www.c-sharpcorner.com/UploadFile/ff2f08/multiple-models-in-single-view-in-mvc/
Way 6: "Using Render Action Method".
But when I Insert Object, Post results were repeated not stop. Help me!
HomeController:
public ActionResult Index()
{
return View();
}
public PartialViewResult ShowPost() {
.......
return PartialView(Posts);
}
public PartialViewResult SavePost()
{
return PartialView("SavePost", new Post());
}
[HttpPost]
public PartialViewResult SavePost(Post post)
{
if (ModelState.IsValid)
{
repository.Insert(post);
return PartialView("Index");//?????????
}
else
{
return PartialView("Index");
}
}
View
"Index" :
#{Html.RenderAction("SavePost","Home");}
#{Html.RenderAction("ShowPost","Home");}
"SavePost":
#model ERichLink.Domain.Entities.Post
#using (Html.BeginForm("SavePost", "Home",FormMethod.Post))
{
#Html.TextBoxFor(model => model.Title)
#Html.TextBoxFor(model => model.CategoryID)
#Html.TextBoxFor(model => model.Description)
<input id="post_btn" value="post"type="submit"/>
}
"ShowPost"
.....
RESULT: I can view Index Page successfully, but when I click submit, Post object insert to db repeat incessantly.

All child actions use their parent http method. So when you first call index method with get, child-renderactions makes http get request too. But when you submit and return index view, then all the child actions inside index view become post. So after submit, it calls http post save method. Then it returns index view. Then it calls again http post save...infinite loop. Best practices never return View() inside PostMethod.
#{Html.RenderAction("SavePost","Home");} executes public ActionResult SavePost()when rendered by any get method executes public ActionResult SavePost(Post post)([HttpPost]) when rendered by any post method.
[HttpPost]
public ActionResult SavePost(Post post)
{
db.Posts.Add(post);
db.SaveChanges();
return RedirectToAction("index");
}
When you make this time, it redirects index action and child-actions inside index view become get request not post.

Related

Having a problem redirecting a form post to another view

I have a basic MVC form that allows a user to submit a zip code and after clicking submit, the user should be redirected to a new view. My code seems to redirect to the next action successfully. However after the redirect, the controller returns back to the original action, so to the user, the page next changed at all.
Here's my View code:
#using (Html.BeginForm("PricingQuote", "Home", FormMethod.Post, new { #class = "rd-mailform text-center offset-top-30" }))
{
<div class="form-group">
<label class="form-label" for="contact-zip">Zip Code</label>
<input class="form-control" id="contact-zip" type="text" name="zip" data-constraints="##Required">
</div>
<button class="btn btn-primary offset-top-30" type="submit">GET STARTED</button>
}
Here's the PricingQuote action in my HomeController. This action redirects to the Pricing action in my Pricing controller:
[HttpPost]
public ActionResult PricingQuote(string zipCode)
{
return RedirectToAction("Pricing", "Pricing");
}
Here's my PricingController:
public class PricingController : Controller
{
// GET: Pricing
public ActionResult Pricing()
{
return View();
}
}
So, after clicking GET STARTED, it accesses my Home/PricingQuote action. This action then tries to redirect to the Pricing/Pricing action, which it does however, the code then seems to (incorrectly) return back to Home/PricingQuote and exits the action.
Any idea how I can redirect & display my Pricing view?
Thanks
Pass the controller in as the second parameter:
[HttpPost]
public ActionResult PricingQuote(string zipCode)
{
return RedirectToAction("Pricing", "PricingController");
}
Thanks for your responses. I was able to figure out my problem. The name of the action I was trying to redirect to ("Pricing") was the same name as my controller ("Pricing"). As a test, I renamed my action to "PricingA" & it worked, so apparently based on this, an action cannot be the same name as the controller when attempting a "RedirectToAction", which I was unaware of (at least that's my assumption based on the results I've found).
Unfortunately, I tried googling for some add'l evidence of this, to provide with this answer, but was unable to find any.
This works:
HomeController:
[HttpPost]
public ActionResult PricingQuote(string zipCode)
{
return RedirectToAction("PricingA", "Pricing");
}
Pricing Controller
[HttpGet]
public ActionResult PricingA()
{
return View();
}

How to redirect to a post action from a get action mvc

I have the following Get action:
[HttpGet]
[AllowAnonymous, OnlyAnonymous]
public ActionResult VerifyVoucherCode()
{
var model = new VerifyVoucherCodeModel();
model.VoucherCode = Request.GetFirstQueryValue("token", "voucherCode");
if (!string.IsNullOrEmpty(model.VoucherCode))
{
// prepopulates the code for the user already in a form
}
return View(model);
}
And a POST action for when the user submits the form:
[HttpPost, AjaxOnly]
[AllowAnonymous, OnlyAnonymous]
[ValidateAntiForgeryToken]
public ActionResult VerifyVoucherCode(VerifyVoucherCode model)
{
return ExecuteAction(() =>
{
// do something
});
}
I want to change the logic so that if the voucher code is in the request, the form is submitted automatically for the user without them having to submit the form themselves (i.e. it takes them straight to that Post action). I've looked at lots of Stack Overflow questions and answers and it seems I cannot redirect to the Post action. I have also tried creating a second Get action which calls the Post action but that does not work either. Does anyone know the correct way to approach this problem?
Thanks
Assuming the model contains a single string for the voucher, you can do something like this:
[HttpGet]
[AllowAnonymous, OnlyAnonymous]
public ActionResult VerifyVoucherCode(string id)
{
if(string.IsNullOrEmpty(id))
{
MyModel model1 = new MyModel();
...
return View(model1);
}
//otherwise process the voucher here
...
return RedirectToAction("SuccessMsg");
}

Razor form not passing back to controller method

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.

Unable to call Post ActionResult from View

I am trying to make a POST request from my View by calling an ActionResult in my Controller. Basically there are a list of events in the view and the user can view the details of the event by clicking the event. This part works. However, once they view the details they also have the ability to sign up for the event. This is the part which is not working.
A sample action I'm trying from the view:
#Html.ActionLink("SignUp", "SignUp", new {id = "2"}, null)
This should access this action result:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SignUp(int id)
{
if (ModelState.IsValid)
{
var registratie = new Registratie(User.Identity.GetUserId(), id);
_db.Registraties.Add(registratie);
_db.SaveChanges();
return RedirectToAction("Index");
}
return View("Index");
}
However, I am getting a 404 error. I think it can't find the actionresult?
The details action result is on the same page however and that works:
// GET: /EventPlanner/Details/5
public ActionResult Details(int id)
{
var evenement = _db.Evenementen.Single(e => e.ID == id);
return View(evenement);
}
I don't understand why the signup gives a 404. Any ideas?
You cant use ActionLink for making POST request. You have following alternatives.
Use submit button to post form
Use Ajax.ActionLink()
Use jQuery.ajax.
I would recommend submit button because I feel it is simpler than the rest.
As an example for first approach. Try this
Razor:
#using (#Html.BeginForm("ActionName", "ControllerName"))
{
<input type="hidden" name="id" value="2" />
<input type="submit" value="Post" />
}
Controller:
public class ControllerNameController : Controller
{
[HttpPost]
public ActionResult ActionName(string id)
{
//Your stuff
return View();
}
}
Its because your Detail Action method is a Get method while your SignUp Action method is decorated with [HttpPost] attribute, which means its a Post method. Remove HttpPost from your action method and it will run.
Edit:
For your purpose, I would recommend you use approaches #Lmadoddin Ibn Alauddin
suggested.
You can put your data under form tag and submit it using submit button(I don't recommend by looking at your code and you have not posted HTML too').
Or:
You can make $.ajax() call with type: 'POST' and pass your data like data: {id: 'idvalue'}.
Hope this will help you. Let me know if you face any problem.

Performing search in Asp.net MVC

I am new to Asp.net MVC and have no idea as to how can i perform the search. Here's my requirement, please tell me how will you handle this :-
I need to have textbox where user can enter a search query or string. The user then clicks on a button or presses enter to submit it. The string needs to matched with a table's property name.
NOTE:- Querying the data and fetching the result isn't the main point here. All I need to know is how will you take the user input and pass it to a controller action or whatever for further processing. Just tell me how will you read the user input and where will you send it to search.
Asp.Net MVC uses standard HTTP verbs. For the html part, it's a normal html form that points to an url. Server side, that url will be routed to a controller/action which will handle the input and do what is needed.
Let's have a sample. You want to make a search form. First of all, it's a best practice to have search forms use the HTTP GET method instead of POST, so the search results can be bookmarked, linked, indexed, etc. I won't be using Html.BeginForm helper method to make things more clear.
<form method="get" action="#Url.Action("MyAction", "MyController")">
<label for="search">Search</label>
<input type="text" name="search" id="search" />
<button type="submit">Perform search</button>
</form>
That's all the html you need. Now you'll have a controller called "MyController" and the method will be something like this:
[HttpGet]
public ActionResult MyAction(string search)
{
//do whatever you need with the parameter,
//like using it as parameter in Linq to Entities or Linq to Sql, etc.
//Suppose your search result will be put in variable "result".
ViewData.Model = result;
return View();
}
Now the view called "MyAction" will be rendered, and the Model of that view will be your "result". Then you'll display it as you wish.
As always in an ASP.NET MVC application you start by defining a view model which will express the structure and requirements of your view. So far you have talked about a form containing a search input:
public class SearchViewModel
{
[DisplayName("search query *")]
[Required]
public string Query { get; set; }
}
then you write a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new SearchViewModel());
}
[HttpPost]
public ActionResult Index(SearchViewModel model)
{
if (!ModelState.IsValid)
{
// There was a validation error => redisplay the view so
// that the user can fix it
return View(model);
}
// At this stage we know that the model is valid. The model.Query
// property will contain whatever value the user entered in the input
// So here you could search your datastore and return the results
// You haven't explained under what form you need the results so
// depending on that you could add other property to the view model
// which will store those results and populate it here
return View(model);
}
}
and finally a view:
#model SearchViewModel
#using (Html.BeginForm())
{
#Html.LabelFor(x => x.Query)
#Html.EditorFor(x => x.Query)
#Html.ValidationMessageFor(x => x.Query)
<button type="submit">Search</button>
}
This is the best way to do it.
Create a ViewModel
public class SearchViewModel
{
public string Query { get; set; }
}
Create a Controller
public class SearchController : Controller
{
[HttpPost]
public ActionResult Search(SearchViewModel model)
{
// perform search based on model.Query
// return a View with your Data.
}
}
Create the View
// in your view
#using (Html.BeginForm("Search", "SearchController"))
{
#Html.TextBox("Query")
<input type="submit" value="search" />
}
hope this helps

Categories