HTTPPOST in MVC not returning view - asp.net-mvc

A simple action method when called with httppost attribute not returning view.but with post perfectly working. Just 2 days back I started learning MVC. For learning purpose I made a simple action to return a view with httppost but it dint work. i searched in forums too but dint get clear idea.. can anybody explain..
[HttpPost]
public ActionResult login(LoginModel loginmodel)
{
if (ModelState.IsValid)
{
}
return View();
}
My view:
<h2>login</h2>
#using (Html.BeginForm())
{
<div class="editor-label">
#Html.LabelFor(model => model.username)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.username)
#Html.ValidationMessageFor(model => model.username)
</div>
<input type="submit" value="Login" />
}

You need to return the viewmodel back to the view.
[HttpPost]
public ActionResult login(LoginModel loginmodel)
{
if (ModelState.IsValid)
{
// to do : check login and redirect
}
// validation failed. let's return to the view.
return View(loginmodel);
}

From the comments from #Shyju's answer you state that you are receiving a 404 error message when you submit the form. This indicates to me that the form's action doesn't have the correct URL. This isn't too surprising as the ASP.NET MVC framework is picking the URL based on some assumptions.
Change the the from declaration in your view to explicitly defined the action name and controller name of your HttpPost login action.
#using (Html.BeginForm("login", "MyControl"))
Replace "MyControl" with the actually name of your controller.

You should define your Controller and Action name in Form like
#using (Html.BeginForm("Action", "Controller"))
And then you need to return the Model in view like
return view(model)
Hope it will help you.

Related

Form submit using partail View error

I have created a form for add comment. I have created it in main View called Index in Home controller. bellow is Index View
private projectDBEntities db = new projectDBEntities();
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
public ActionResult AddComment()
{
return PartialView("_Comment");
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddComment(comment cmt)
{
if (ModelState.IsValid)
{
db.comments.Add(cmt);
db.SaveChanges();
return RedirectToAction("Index", "Home");
}
return PartialView("_Comment", cmt);
}
below is _Comment Partial View
#using (Html.BeginForm()) {#Html.AntiForgeryToken()#Html.ValidationSummary(true)
<fieldset>
<legend>comment</legend>
<div class="editor-label">
#Html.LabelFor(model => model.cmd_content)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.cmd_content)
#Html.ValidationMessageFor(model => model.cmd_content)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.t_email)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.t_email)
#Html.ValidationMessageFor(model => model.t_email)
</div>
<p>
<input type="submit" value="Comment" />
</p>
</fieldset>}
System.Web.HttpException was occuerd. I want to know What is the reason behind this error and what is the best method to form submit using partail View.
Id have to agree with Sandip's answer here, but to elaborate ..
#using (Html.BeginForm("AddComment", "Home"))
{
//Content to send to the server-side
}
As long as your model in your partial view points to your 'Comment' object, then this should work fine when using #Html.EditorFor(). In your controller, your already waiting for your 'Comment' object to be populated. So on Post, when the submit is clicked, it will populate that object.
Hope this helps.
#using (Html.BeginForm("AddComment", "Home"))
{
}

Can i have more than one Post method in asp.net mvc controller?

I have two views, one is CustomerDetail.cshtml and another is PAymentDetail.cshtml and i have one controller QuoteController.cs.
Both the Views has Submit buttons and HTTPPOST method for both the views are in QuoteController.cs.
[HttpPost]
public ActionResult CustomerDetail(FormCollection form)
{
}
[HttpPost]
public ActionResult PAymentDetail(FormCollection form)
{
}
Now, when i click on Submit button of Payment details, it is calling/routing to HttpPost method of CustomerDetail rather than PAymentDetail.
Could anyone help me on this?? What i'm doing wrong? Both The form method is POST.
For the PaymentDetail, you use this in the view:
#using(Html.BeginForm("PAymentDetail","Quote",FormMethod.Post))
{
//Form element here
}
The result html will be
<form action="/Quote/PAymentDetail" method="post"></form>
The same for customer Detail
#using(Html.BeginForm("CustomerDetail","Quote",FormMethod.Post))
{
//Form element here
}
Hope that help. Having two post methods in the same controller is not a problems, as long as these methods have different names.
For a better way other than FormCollection, I recommend this.
First, you create a model.
public class LoginModel
{
public string UserName { get; set; }
public string Password { get; set; }
public bool RememberMe { get; set; }
public string ReturnUrl { get; set; }
}
Then, in the view:
#model LoginModel
#using (Html.BeginForm()) {
<fieldset>
<div class="editor-label">
#Html.LabelFor(model => model.UserName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.UserName)
//Insted of razor tag, you can create your own input, it must have the same name as the model property like below.
<input type="text" name="Username" id="Username"/>
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Password)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Password)
</div>
<div class="editor-label">
#Html.CheckBoxFor(m => m.RememberMe)
</div>
</fieldset>
}
These user input will be mapped into the controller.
[HttpPost]
public ActionResult Login(LoginModel model)
{
String username = model.Username;
//Other thing
}
Good luck with that.
Absolutely! Just ensure you are posting to the right action method, check your rendered HTML's form tags.
Also, the FormCollection isn't a good design for MVC.
If you want to have only one url, here is another approach: http://www.dotnetcurry.com/ShowArticle.aspx?ID=724
The idea is to use a form element (the button or a hidden element) to decide, which form has been submitted. Then you write a custom action selector (http://msdn.microsoft.com/en-us/library/system.web.mvc.actionmethodselectorattribute.aspx) which decides which action will be invoked.

MVC4 Razor Multiple strongly type partial view with action in one page

I have a requirement where I have Login and Register form in Homepage. I believe this quite a common scenario however I am having difficulty achieving this.
This Login and Register forms are two separate Strongly Type Partial View which is being used in Index view
Below is the controller for Register. I will skip the login since if I get this to work, the other should be similar.
Register Controller
//
// GET: /Account/Register
[AllowAnonymous]
public ActionResult Register()
{
return PartialView();
}
//
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel registerModel)
{
if (ModelState.IsValid)
{
// Attempt to register the user
try
{
_webSecurity.CreateUserAndAccount(registerModel.Email, registerModel.Password,
new { registerModel.FirstName, registerModel.LastName, registerModel.Email });
_webSecurity.Login(registerModel.Email, registerModel.Password);
return RedirectToAction("Manage", "Account");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
// If we got this far, something failed, redisplay form
return View(registerModel);
}
Index Controller
//
// GET: /Home/
public ActionResult Index()
{
//
// If logedin redirect to profile page
// Else show home page view
//
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
if (Request.IsAuthenticated)
{
return RedirectToAction("Manage", "Account", new { id = HttpContext.User.Identity.Name });
}
return View();
}
Register View
#using System.Web.Optimization
#model BoilKu.Web.ViewModels.RegisterModel
#using (Html.BeginForm("Register","Account", FormMethod.Post)) {
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<fieldset>
<legend>Registration Form</legend>
<ol>
<li>
#Html.LabelFor(m => m.FirstName)
#Html.TextBoxFor(m => m.FirstName)
</li>
...
... Omitted codes
...
<li>
#Html.LabelFor(m => m.Password)
#Html.PasswordFor(m => m.Password)
</li>
</ol>
<input type="submit" value="Register" />
</fieldset>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Index View
#model BoilKu.Web.ViewModels.HomeModel
#{
ViewBag.Title = "Home Page";
}
#{
Html.RenderAction("Login", "Account");
}
#{
Html.RenderAction("Register", "Account");
}
Now with the above code, I have managed to get the partial view to display on the homepage. However when I click "Register" after filling up the details it will automatically redirect to my Register page with the fields pre populated. This is not what I want. I expect the register to happened on the homepage and redirect to Profile page when it has successfully registered. How do I go about doing this? Thank you for reading and apology for the noobishe questions. I am still quite new to MVC.
Update
Changing the Register Controller return from PartialView() to View() will act according the above requirement. However it will embed the page into a page. (i.e. the top navigation will be duplicated. )
Anyone?
I think it is better to create a partial page (user control) for register view
_register.cshtml
(no change here, just removed the script section. Parent view will render necessary script)
#using System.Web.Optimization
#model BoilKu.Web.ViewModels.RegisterModel
#using (Html.BeginForm("Register","Account", FormMethod.Post)) {
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<fieldset>
<legend>Registration Form</legend>
<ol>
<li>
#Html.LabelFor(m => m.FirstName)
#Html.TextBoxFor(m => m.FirstName)
</li>
...
... Omitted codes
...
<li>
#Html.LabelFor(m => m.Password)
#Html.PasswordFor(m => m.Password)
</li>
</ol>
<input type="submit" value="Register" />
</fieldset>
}
index.cshtml
inside the HomeModel, it needs to have a RegisterModel property
#model BoilKu.Web.ViewModels.HomeModel
#{
ViewBag.Title = "Home Page";
}
#{
Html.RenderAction("Login", "Account");
}
#{
#Html.Partial("register", Model.RegisterModel)
}
When I create a MVC application, i usually retrieve all the information that is required by the page and put it into the model. In this scenario, HomeModel contains RegisterModel details. Then inside the view, you can render partial page and just pass the model as an argument. Partial view doesn't have to go back to the controller.
Then in your Register page, you can partial render
#Html.Partial("register", Model.RegisterModel)

Create reusable form contact component in asp.net mvc

I'm newbie at asp.net mvc, I'm trying to develop a reusable contact form component for asp.net mvc .
I have tryed to do it creating a PartialView with a form, I don't know if this is the better approach, for create a reusable component
My PartialView is
#model MyModel.ContactData
#using (Html.BeginForm("ContactForm", "ContactForm", FormMethod.Post)) {
<fieldset>
<p>
#Html.LabelFor(model => model.MailAddress)
#Html.EditorFor(model => model.MailAddress)
</p>
<p>
#Html.LabelFor(model => model.Message)
#Html.TextAreaFor(model => model.Message)
</p>
<input type="submit" value="Save" />
</fieldset>
}
The problems start with the controller, the controller is a specific controller for only this partialView.
public class ContactFormController : Controller
{
[HttpPost]
public ActionResult ContactForm(ContactData contactData)
{
if (ModelState.IsValid)
{
return PartialView("MessageSend");
}
return PartialView();
}
}
My problem is in case of some of the required fields are empty, in that case the controller returns only the partial view, not returning the partival view inside its parent context. I have tryed calling the PartialView from parent View as #Html.Partial, #Html.RenderAction, #Html.RenderPartial and the same occurs.
How can I return the partial view Inside it's parent Context? I have tried with
return View(ParentViewsName, contactData) but I dislike it because on form submitting it changes the url on address bar from /Contact to /ContactForm/ContactForm.
Perphaps I'm trying to create a reusable component with a wrong approach? It's better to update with ajax only the PartialView? Alternatives?
Thanks
From my understanding, you wish to display status message which is a partial view after user successfully submits the form. I think tempdata will be apt for this kind of situation.
public class ContactFormController : Controller
{
[HttpPost]
public ActionResult ContactForm(ContactData contactData)
{
if (ModelState.IsValid)
{
TempData["success"] = true;
return RedirectToAction("parentpage");
}
return View(contactData);
}
}
In parent page, check whether TempData["success"] is null and display the partial view "MessageSend".
Finally as Sundeep explains I have done this with ajax like this example Partial ASP.NET MVC View submit.
Thanks for your help.

Get value of view element in MVC that not relevant to model

When I have a DropDownList that relevant to Model of view like this:
#Html.DropDownListFor(model => model.Group.Name, selectList)
I Can retrieve Values in controller as follow:
string SelectedGroupName = collection.GetValue("Group.Name").AttemptedValue;
But now I have a DropDownList that not relevant to model but I need the value of that, this is my new DropDown:
#Html.DropDownList("DDName", selectList)
How can I retrieve the selected value of that in controller? is there any hiddenfield or other thing to pass value from view to controller?
Edit
This is my view:
#model PhoneBook.Models.Numbers
#{
ViewBag.Title = "Delete";
}
<h2>
Move And Delete</h2>
<fieldset>
<legend>Label of Numbers</legend>
<div class="display-label">
Delete Label And Move All Numbers with: #Html.DisplayFor(model =>
model.Title)</div>
<div class="display-field">
To #Html.DropDownList("DDName", selectlist)
</div>
</fieldset>
#using (Html.BeginForm()) {
<p>
<input type="submit" value="Move Numbers And Delete Label" name="MDbtn" />
</p>
}
This is my Controller:
[HttpPost]
public ActionResult Delete(int id, FormCollection collection) {
var result = Request["DDName"];
//Use result
return RedirectToAction("Index");
}
but result set to null, why?
I think this must be work:
[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
{
var dd = collection.GetValue("DDName");
.....
}
I think all you have to do is
In your view:
put #using (Html.BeginForm()) { above the <fieldset>, so the #Html.DropDownList("DDName", selectlist) is inside it.
In your controller:
public ActionResult Delete(int id, FormCollection collection, string DDName)
{ [...] }
And I'm fairly sure MVC3 will automagically give you the selected value as parameter to your controller.
If that does not work, try object DDName in your controller instead.
Think the ddl has to be in your form if you want to pass the value in through the form collection
Your problem is, that your dropdown isn't contained inside the form in your view.
You have to put it after BeginForm:
#using (Html.BeginForm()) {
<div class="display-field">
To #Html.DropDownList("DDName", selectlist)
</div>
<p>
<input type="submit" value="Move Numbers And Delete Label" name="MDbtn" />
</p>
}
Then you have can use FormCollection or a designated parameter. The default Modelbinder will work with both approaches:
ActionResult Action (FormCollection collection, string DDName)
You can easily check those issues with fiddler.

Resources