Submitting a form view to controller - asp.net-mvc-3

I have a form in my form view defined as
using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
This form contins a number of input of type button and button
<input type="submit" value="val1" name="action">
<input type="submit" value="val2" name="action">
<input type="submit" value="val3" name="action" />
<button class="button" type="submit" name="action" value="val4">Val4</button>
I have 2 controllers for this view
Public ActionResult form{
}
and
[HttpPost]
public ActionResult form(String button)
{
switch (actionType)
{
case "val1":
return RedirectToAction("AnotherView");
case "val2":
return RedirectToAction("AnotherView2");
default:
return RedirectToAction("AnotherView3");
}
}
But whichever button I click, I am being redirected to the Home defined in the form
using (Html.BeginForm("Index", "Home",
My question is how can I fix this and how can I be certain that this post method is bound to my view as i just typed it in?

using (Html.BeginForm("action_name", "controllername", FormMethod.GET, new { enctype = "multipart/form-data" }))
use input type select:
<select name="action">
<option value="val1" >val1</option>
<option value="val2" >val2</option>
<option value="val3" >val3</option></select>
and method at controller
public ActionResult action_name(String action){
switch (action)
{
case "val1":
return RedirectToAction("AnotherView");
case "val2":
return RedirectToAction("AnotherView2");
default:
return RedirectToAction("AnotherView3");
}
}

If you specify a form field named action MVC will interpret this as the action on the controller to route to. Thus clicking val1 will ultimately execute the method:
public ActionResult val1()
{
}
If this method does not exist, your error handling will take over.
Solution: Don't use action as a name of a form field.

Related

Load/Refresh only part of a page (View) using AJAX in ASP.NET MVC

I am trying to achieve the same result as mentioned by the OP in this post However when I try to render partial view by checking if it was an AJAX request in my Index action, its evaluating to false.
My Index View:
#using (Ajax.BeginForm("Index", "Home",
new AjaxOptions()
{
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "restaurantList"
}))
{
<input type="search" name="searchTerm" />
<input type="submit" value="Search By Name" />
}
#Html.Partial("_Restaurant",Model)
My Partial View:
<div id="restaurantList" style="border:2px dotted red; padding-left:2em; margin-top:4px;">
#foreach (var item in Model)
{
<div>
<h4>#item.Name</h4>
<div>#item.City, #item.Country</div>
<div>#item.CountOfReviews</div>
<hr />
</div>
}
</div>
My Index Action:
public ActionResult Index(string searchTerm = null)
{
var model = ...//Building model object here
if (Request.IsAjaxRequest())
{
return PartialView("_Restaurant", model);
}
return View(model);
I would prefer not to dive into use of any jQuery or javascript as I am in the process of learning ASP.NET MVC, and would want to know why the approach I took is not working? The second answer by Dennis, in the post that I referenced also suggested similar approach.
Could someone kindly tell me what I am doing wrong?
Thanks
This is just an example how you can load view from AJAX without page refresh, it may help you.
It send text value to controller by ajax call and load that value in other view which replace main view, if you don't want to replace main view then you can take other div instead same div to load content.
Controller:
public ActionResult Index()
{
return View();
}
[HttpPost]
public PartialViewResult TestAjax(string Name)
{
ViewBag.Name = Name;
return PartialView();
}
Index.cshtml:
<input type="button" id="btnSearch" class="btn btn-warning" style="height:35px;width:120px" value="Search"/>
<label>Name:</label><input type="text" id="txtName" name="txtName" />
<script>
$('#btnSearch').click(function () {
$.ajax({
url: '#Url.Action("TestAjax", "Home")',
data: { Name: $("#txtName").val() },
type: 'POST',
success: function (data) {
$("#divContent").html(data);
}
});
});
</script>
TestAjax.cshtml:
#ViewBag.Name
As #StephenMuecke pointed out in his comments, the libraries not being loaded correctly was the problem. While creating a new bundle of all libraries and adding it in the BundkeConfig.cs I had missed ~/Scripts/jquery.unobtrusive-ajax.js*. Got it working now.

MVC3 form posting with value and file

I am new to MVC3 and I would like to create a form with input column and file upload.
The problem comes when I try to do both thing at the same time.
Here is my code
...
[HttpPost]
public ActionResult About(string inputStr)
{
string local = inputStr;
string[] word = inputStr.Split(':');
return View();
}
[HttpPost]
public ActionResult GetFile(string inputStr, HttpPostedFileBase file)
{
string filename = file.FileName;
return RedirectToAction("About");
}
These two are my controllers
#using (Html.BeginForm("GetFile", "Home", (new { inputStr = "111" }), FormMethod.Post, new { enctype = "multipart/form-data" })){
<div class="editor">
<input type="file" name="file" />
<input type="submit" value="OK" id="submitFile" class="testingSubmit"/>
</div>
}
This code works well for uploading files, and sending string "111" to the controller.
Here is another jQuery function
$('.testingSubmit').click(function () {
var totalString="";
$('.editor-field :input').each(function () {
alert($(this).val());
totalString += $(this).val().toString() + ":";
});
$('form').submit();
/* $.post("About", { inputStr: totalString}, function (data) {
});*/
});
Here, what I am trying to do is the get the user input and put it on string totalString.
I was able to post the totalString to the controller by using $.post
My questions are:
1. Am i on the right track? i.e. Is that possible to do those two tasks together with one post?
2. If not, what are the possible solution for this?
Thank you very much for your attention and hopefully this can be solved!
I think something like this should work:
#using (Html.BeginForm("GetFile", "Home", (new { inputStr = "111" }), FormMethod.Post, new { #id = "frmGetFile", enctype = "multipart/form-data" })){
<div class="editor">
<input type="file" name="file" />
<input type="hidden" name="totalString" id="totalString"/>
<input type="submit" value="OK" id="submitFile" onclick="submitGetFileForm()" class="testingSubmit"/>
</div>
}
JavaScript:
function submitGetFileForm(e)
{
e.preventDefault();
var total = //build your total string here
$('#totalString').val(total);
$('#frmGetFile').submit();
}
Controller:
[HttpPost]
public ActionResult GetFile(string totalString, HttpPostedFileBase file)
{
// your action logic..
}

How to use hidden field values from view to controller in asp.net mvc 3

I have to pass hidden filed values to controller action. So I have tried in the following way, but I am getting null values.
I have tried both methods i.e formcollection and viewmodel concept
Controller
public ActionResult MapIcon()
{
Hidden hd = new Hidden();
return View(hd);
}
[HttpPost]
public ActionResult MapIcon(Hidden hidden)
{
var value=hidden.hiddevalue;//null
FormCollection col = new FormCollection();
var value = col["hidden1"];
// string value = mycontroler.ControlName;
return View(hidden);
}
View
#model SVGImageUpload.Models.Hidden
Razor view:#using (Html.BeginForm(new { id = "postform" }))
{
<input type="hidden" id="" value="7" name="hidden1" />
<input type="hidden" id="" value="7" name="hidden2"/>
<input type="submit" value="Match"/>
}
Viewmodel
public class Hidden
{
public string hiddevalue { get; set; }
}
Try this, In Razor view:
#using (Html.BeginForm(new { id = "postform" }))
{
#Html.HiddenFor(m=>m.hiddevalue)
<input type="submit" value="Match"/>
}
It seems to me like you are trying to get multiple values into the POST controller. In that case, and by your exam, the value from the hidden input is enough. In that case, you can setup your controller as so:
public ActionResult Index()
{
Hidden hd = new Hidden();
return View(hd);
}
[HttpPost]
public ActionResult Index(IEnumerable<string> hiddens)
{
foreach (var item in hiddens)
{
//do whatter with item
}
return View(new Hidden());
}
and as for your view, simple change it in order to bind to the same name "hiddens" as so:
#using (Html.BeginForm(new { id = "postform" }))
{
<input type="hidden" value="7" name="hiddens" />
<input type="hidden" value="2" name="hiddens" />
<input type="submit" value="Match" />
}
Hope this serves what you are looking forward to.
if your hidden value is static.Than try this
View
#using (Html.BeginForm(new { id = "postform" }))
{
#Html.HiddenFor(m=>m.hiddevalue)
<input type="hidden" id="" value="7" name="hidden1" />
<input type="hidden" id="" value="7" name="hidden2"/>
<input type="submit" value="Match"/>
}
Controller
[HttpPost]
public ActionResult MapIcon(Hidden hidden, string hidden1, string hidden2)
{
var hiddenvalue = hidden.hiddevalue;
var hiddenvalue1 = hidden1;
var hiddenvalue2 = hidden2;
var value=hidden.hiddevalue;//null
FormCollection col = new FormCollection();
var value = col["hidden1"];
// string value = mycontroler.ControlName;
return View(hidden);
}
Script
$(document).ready(function () {
$('#hiddevalue').val("Jaimin");
});

mvc3: html.beginform search returning empty querystring

In an MVC3 app, i have the following View:
#using (Html.BeginForm("Index", "Search", new {query = #Request.QueryString["query"]}, FormMethod.Post))
{
<input type="search" name="query" id="query" value="" />
}
When i type in the url "/Search?query=test", Request.Querystring in my Index action reads out the search-value perfectly well (i have my routes set to ignore the Action in the url). When i type it in the seachbox, it hits the right action and controller (so the routing seems fine) but the querystring remains empty. What am i doing wrong?
The Problem is that you are look in the Request.QueryString collection. But you are doing a POST so the query value is in the Request.Form Collection. But i think you want your TextBox filled with the data so can do it like in my sample.
Sample
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
<input type="search" name="query" id="query" value="#Request.Form["query"]" />
}
But this is not the real MVC approach. You should create a ViewModel for that.
Model
namespace MyNameSpace.Models
{
public class SearchViewModel
{
public string Query { get; set; }
}
}
View
#model MyNameSpace.Models.SearchViewModel
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
#Html.TextBoxFor(x => x.Query)
<input type="submit" />
}
Controller
public ActionResult Index()
{
return View(new SearchViewModel());
}
[HttpPost]
public ActionResult Index(SearchViewModel model)
{
// do your search
return View(model);
}

Validation firing for both controls

I currently have two partial views on a single page, added with:
#Html.Action("_LogonBox","Account")
#Html.Action("_TrackingBox","Tracking")
each has its own form and model...
but if I enter values into the _logonbox view and submit it it causes the validation to fire on the TrackingBox and because the values in tracking box are empty it highlights the textboxes as errors.
How do I sort this out, in webforms it was simply validationGroups?
EDIT
here is the markup:
LogOn View
#model Models.LogonModel
#using (Html.BeginForm("Login", "account", FormMethod.Post, new { Id = "Login" }))
{
<div class="boxwrapper">
<div class="loginbox">
<a href="#" style="float: right; color: #fff; font-size: 95%%; padding: 5px 10px;">Forgotten
Password?</a>
<h3>
My Account</h3>
<div class="content">
<fieldset class="logincontrols">
<table>
<tr>
<td class="loginlabel">
#Html.LabelFor(m => m.UserName)
</td>
<td class="logintextbox">
#Html.TextBoxFor(m => m.UserName, new { ValidationGroup = "Account" })
</td>
</tr>
<tr>
<td class="loginlabel">
#Html.LabelFor(m => m.Password)
</td>
<td class="logintextbox">
#Html.PasswordFor(m => m.Password, new { ValidationGroup = "Account" })
<input type="image" value="Sign In" src="/Content/Images/buttons/signin.png" style="vertical-align: bottom;" ValidationGroup="Account" />
</td>
</tr>
</table>
</fieldset>
</div>
</div>
</div>}
Tracking View
#model .Models.TrackingModel
#using (Html.BeginForm("Index", "Tracking", new { Id = "Tracking" }))
{
<div class="boxwrapper">
<div class="bluebox">
<fieldset class="logincontrols">
<h3>
Shipment Tracking</h3>
<div class="content">
<p style="text-align: left;">
Please enter your reference number:</p>
#Html.TextBoxFor(m => m.TrackingNumber)
<br />
<p style="text-align: right; margin-top: 10px;">
<input type="image" value="Track Shipment" src="/Content/Images/buttons/trackingbutton.png" /> </p>
</div>
<fieldset>
</div>
</div>
}
Further EDIT
added controllers as requested
public class TrackingController : Controller
{
//
// GET: /Tracking/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(TrackingModel model)
{
return View(model);
}
[HttpPost]
public PartialViewResult _TrackingBox(TrackingModel model)
{
return PartialView(model);
}
public PartialViewResult _TrackingBox()
{
return PartialView();
}
}
public class AccountController : Controller
{
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, false);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
public PartialViewResult _Logonbox()
{
return PartialView();
}
[HttpPost]
public PartialViewResult _Logonbox(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
//do something here
}
// If we got this far, something failed, redisplay form
return PartialView(model);
}
}
I have managed to fix this, but if someone can comment on WHY this fixes it that would be great.
I changed the #Html.Action("_partialViewName") to #Html.Partial("_partialViewName"), and this caused the same problems.
To fix this I had to include a new model object as below.
#Html.Partial("_LogonBox", new TGEFreight.UI.Web.Models.LogOnModel())
#Html.Partial("_TrackingBox", new TGEFreight.UI.Web.Models.TrackingModel())
As to why this works I dont know, this is probably due to my infancy with MVC, but this is the answer anyway.
Thanks for the help guys.
I'm guessing that both of these field sets are wrapped in the same <form>. You can get around this by having a separate <form> for each partial / child action.
Unlike webforms, MVC lets you take full advantage of HTML, meaning you can have more than 1 form on a page. In webforms, everything needed to be on 1 page so that viewstate could be persisted for the entire page during each postback.
If you are using jquery unobtrusive validation, validations only fire for the form that was submitted.
Edit
Sorry, I re-read your question and you say each of these has its own form. Can you show more of the razor markup? What does your submit button look like? Are there any jquery or javascript behaviors attached to the forms? Is validation firing on the client or the server?
Update
Have you tried using #Html.Partial instead of #Html.Action? Html.Action results in a new HTTP request to the child action method. What view does your login action on your account controller return? It could be that the login POST is calling the tracking action as a POST, and causing validation to fire on it.
I agree with #olivehour you should try using #Html.Partial instead of #Html.Action. Now when you say that if you use Partial that you can't define the action for them to use, what exactly do you mean. You should be able to define an HttpGet and HttpPost action without a problem for each of the partials, so for instance as an example you should be able to easily do the following:
public class AccountController : Controller
{
...
[HttpGet]
public ActionResult Login()
{
return PartialView();
}
[HttpPost]
public ActionResult Login(LoginModel model)
{
... Validate Model & additional logic
// return some redirect action
}
}
I noticed that in your post you are simply returning the PartialView again, was that just pseudo code? If not, at least for the login partial, I would assume that if someone logs in that the post action would redirect them to another page. In either case you would display the partial view by using #Html.Partial or #{Html.RenderPartial(...);} in your calling view. Hope that helps.

Resources