MVC HTTP Post input return null - asp.net-mvc

Controller:
public ActionResult MyController()
{
ViewBag.DateNow = DateTime.Now.ToString("yyyy-MM-dd");
}
[HTTPPost]
public ActionResult MyController(string fromDate)
{
ViewBag.DateNow = fromDate;
}
View:
#using (Html.BeginForm("MyController", "Account", FormMethod.Post))
{
//datepicker class: bootstrap-datepicker.js
<input id="fromDate" type="text" class="datepicker" />
<buttontype="submit" value="Search" class="btn btn btn-primary">
Search
</button>
}
What I'm trying to achieve is before POST the data that pass into ViewBag.DateNow is the current date and it successfully bring in to the view. However when I'm trying to fill up the input form with (eg: 2016-05-10) and click on the Search button. But seems like the fromDate string return NullReferenceException. I'm trying out with some solution online but I still can't get it right and that's why I decided to get this posted up. Thanks in advance!

For this to work properly you need to specify the name attribute in your textbox. It needs to be the same value as the input variable in your HTTP post action method, namely fromDate. Currently the id attribute is set to fromDate:
<input id="fromDate" name="fromDate" type="text" value="#ViewBag.DateNow" />
If you do not specify this name attribute then when you post your form fromDate will always be null. Specifying it like above will make sure that fromDate will always have a value (if entered).
I want to go a bit off-topic here, I would like to suggest that you make use of view models for your form submissions. Instead of having individual input variables in your action method you can just have your view model as input parameter.
I wrote an answer as to what view models are here, please go and read it if you have the time:
What is ViewModel in MVC?
Working on your example, I would have a view model that contains just one property, namely FromDate. FromDate will contain the value in your textbox. It is setup as a string because you want to pass it a formatted date value:
public class TestModel
{
public string FromDate { get; set; }
}
This value will be set in your HTTP get action method and the view model will be sent to the view:
public ActionResult Index()
{
TestModel model = new TestModel();
model.FromDate = DateTime.Now.ToString("yyyy-MM-dd");
return View(model);
}
In your view you will accept this view model and create the form accordingly:
#model WebApplication_Test.Models.TestModel
#using (Html.BeginForm())
{
#Html.TextBoxFor(m => m.FromDate)
<button type="submit">Search</button>
}
When you submit this form, you need an HTTP post action method to handle the submission. Because the view is bound to the view model, the action method will accept it as an input parameter:
[HttpPost]
public ActionResult Index(TestModel model)
{
// Do what you need to do
string date = model.FromDate;
return View(model);
}
Your way of doing it is also correct. I have just shown you an alternative way to do it. Some day you might have a huge form with many input values, then my approach will be 'cleaner'.

Try this:
1) Replace with [HttpPost] instead of [HTTPPost]
2) You should add name=" " for input like this:
<input id="fromDate" name="fromDate" type="text" class="datepicker" />

Related

How To Pass Value Entered In A Text Box To An Action Method

I was building a Movies application using MVC. CRUD was automatically created for me by Visual Studio. Now, I am trying to build a Search functionality for the user. Here is the code I wrote:
#using (Html.BeginForm("SearchIndex", "Movies", new {searchString = ??? }))
{
<fieldset>
<legend>Search</legend>
<label>Title</label>
<input type ="text" id="srchTitle" />
<br /><br />
<input type ="submit" value="Search" />
</fieldset>
}
I have built the SearchIndex method and the associated view. I just can't find how to pass the value entered in the text box to the SearchIndex action method.
Please help.
In your Model:
public class Search
{
public String SearchText { get; set; }
}
Make your View strongly typed and use
#Html.EditorFor(model => model.SearchText)
In your Controller:
[HttpPost]
public ActionResult SearchIndex(Search model)
{
String text = model.SearchText;
}
Hope this helps.
You need to give your input field a name:
<input type="text" id="srchTitle" name="movieToFind" />
Then in your Controller make sure it has a string parameter:
in MoviesController:
[System.Web.Mvc.HttpPost]
public ActionResult SearchIndex(string movieToFind)
{
//Controller Action things.
}
Note: Form fields names must match the parameters expected in the controller. Or map to model properties if a 'Model' is expected.

Using webforms in MVC

I am learning MVC, following THIS tutorial. (link will take you directly to where i'm stuck). so far I have learnt, there's a controller for every view. Now i have to take input from user through web entry form as mentioned in tutorial. In my project, i have a controller named Default1 and i can run it as localhost:xyz/Default1/Index. it runs perfect.
Then i created a new Controller, named Default2 and bound it to some view to display some data, and it worked perfect as localhost:xyz/Default2/Displaycustomer. the customer information was static (hard coded). and controller is as:
public ViewResult DisplayCustomers()
{
Customer cobj = new Customer();
cobj.Code = "12";
cobj.Name = "Zeeshan";
cobj.Amount = 7000;
return View("DisplayCustomers",cobj);
}
Now i have to take input from User, regarding cutomer iformation, using html page as mentioned in tutorial. so i tried adding a new webform under view folder, and and modified my controller as:
[HttpPost]
public ViewResult DisplayCustomers()
{
Customer cobj = new Customer();
cobj.Code = Request.Form["Id"].ToString();
cobj.Name = Request.Form["Name"].ToString();
cobj.Amount = Convert.ToDouble(Request.Form["Amount"].ToString());
return View("DisplayCustomers",cobj);
}
My Question is: How can i make my project stared, so that it takes input first, and then displays it, using above controller? Did i add the webform at right location? What would be the link to run it? i tried localhost:xyz/Default2/entryform etc. but failed.
(in my entryform.aspx, i have mentioned form action="DisplayCustomer" )
It sounds like what you're missing is an action to just display the form. In otherwords, you just need an action to display a form. That form's POST action should reference your controller's DisplayCustomers action.
So in your controller code:
public class CustomerController : Controller
{
[HttpGet]
public ViewResult New()
{
return View("NewCustomer"); //Our view that contains the new customer form.
}
// Add your code for displaying customers below
}
And in your view, you have code like this
#using(Html.BeginForm("DisplayCustomers", "Customer")) {
<!-- Add your form controls here -->
}
Notice that I'm using the version of the BeginForm helper that specifies the action method and controller to call. This will write the form tag to post back to your DisplayCustomers action. Here is the equivalent HTML:
<form method="POST" action="/Customer/DisplayCustomers">
You would then access your form using the URL http://test.server/Customer/New.
This may not be the best example in the world...but this will at least get you rolling..
url would be:localhost:1234/Home/Customer
the controller
public ActionResult Customer()
{
return View();
}
[HttpPost]
public ActionResult Customer(FormCollection frm)
{
var name = frm["name"].ToString();
var address = frm["address"].ToString();
ViewBag.Name = name;
ViewBag.Address = address;
return View();
}
The view
<div>
#using (Html.BeginForm())
{
<input type="text" name="name" id="name" />
<input type="text" name="address" id="address"/>
<input type="submit" name="submit" value="submit" />
<input type="text" name="namedisplay" value='#ViewBag.Name'/>
<input type="text" name="addressdisplay" value='#ViewBag.Address'/>
}
</div>

string Model, passing value to controller issue

I have a ASP.NET Razor view which binds to string. Its very simple:
#model string
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
Hello, #Model
#using(Html.BeginForm())
{
<fieldset>
<label for="name" style="color: whitesmoke">Name:</label>
<input type="text" id="name"/>
<br/>
<input type="submit" value="Submit"/>
</fieldset>
}
And a simple controller:
[HttpGet]
public ActionResult Index()
{
object model = "foo";
return View(model);
}
private string name;
[HttpPost]
public ActionResult Index(string name)
{
return View();
}
When I push the submit button, the Index Post action result triggers, but the 'string name' parameter is null. Isn't Razor smart enough to automatically bind this property to my controller from the view because the input id matches the name of the param on the controller? If not, how do I bind this? I know with a model with properties I can use Html.HiddenFor(m => m.Foo), but since there's no properties, I don't know how to call this method properly.. I can set it properly calling Html.Hidden("name","foo"), but I don't know how to pass a the value here. I know I can use jquery call such as:
#Html.Hidden("name", "$('input[id=name]').val())");
This literally sends the jquery string to the controller as the value... I'm not sure what to do at this point. Thanks!
It is smart enough to bind the property, just give your input a name which matches with the action parameter:
<input type="text" id="name" name="name" />

ASP.NET MVC, passing Model from View to Controller

I'm having trouble with ASP.NET MVC and passing data from View to Controller. I have a model like this:
public class InputModel {
public List<Process> axProc { get; set; }
public string ToJson() {
return new JavaScriptSerializer().Serialize(this);
}
}
public class Process {
public string name { get; set; }
public string value { get; set; }
}
I create this InputModel in my Controller and pass it to the View:
public ActionResult Input() {
if (Session["InputModel"] == null)
Session["InputModel"] = loadInputModel();
return View(Session["InputModel"]);
}
In my Input.cshtml file I then have some code to generate the input form:
#model PROJ.Models.InputModel
#using(Html.BeginForm()) {
foreach(PROJ.Models.Process p in Model.axProc){
<input type="text" />
#* #Html.TextBoxFor(?? => p.value) *#
}
<input type="submit" value="SEND" />
}
Now when I click on the submit button, I want to work with the data that was put into the textfields.
QUESTION 1: I have seen this #Html.TextBoxFor(), but I don't really get this "stuff => otherstuff". I concluded that the "otherstuff" should be the field where I want to have my data written to, in this case it would probably be "p.value". But what is the "stuff" thing in front of the arrow?
Back in the Controller I then have a function for the POST with some debug:
[HttpPost]
public ActionResult Input(InputModel m) {
DEBUG(m.ToJson());
DEBUG("COUNT: " + m.axProc.Count);
return View(m);
}
Here the Debug only shows something like:
{"axProc":[]}
COUNT: 0
So the returned Model I get is empty.
QUESTION 2: Am I doing something fundamentally wrong with this #using(Html.BeginForm())? Is this not the correct choice here? If so, how do I get my model filled with data back to the controller?
(I cannot use "#model List< Process >" here (because the example above is abbreviated, in the actual code there would be more stuff).)
I hope someone can fill me in with some of the details I'm overlooking.
Change your view to some thing like this to properly bind the list on form submission.
#using(Html.BeginForm()) {
for(int i=0;i<Model.axProc.Count;i++){
<span>
#Html.TextBoxFor(model => model.axProc[i].value)
</span>
}
<input type="submit" value="SEND" />
}
In #Html.TextBoxFor(stuff => otherstuff) stuff is your View's model, otherstuff is your model's public member.
Since in the View you want to render input elements for the model member of a collection type (List), you should first create a separate partial view for rendering a single item of that collection (Process). It would look something like this (name it Process.cshtml, for example, and place into the /Views/Shared folder):
#model List<PROJ.Models.Process>
#Html.TextBoxFor(model => p.value)
Then, your main View would look like this:
#model PROJ.Models.InputModel
#using(Html.BeginForm()) {
foreach(PROJ.Models.Process p in Model.axProc){
#Html.Partial("Process", p)
}
<input type="submit" value="SEND" />
}
Also, check that the loadInputModel() method actually returns something, e.g. not an empty list.

FormsCollection in Mvc Controller method - any other way of accessing?

I have a form which I want to post to ensure the page refreshes on posting the data (not the ajax way). The problem is really I only want to post the Id of the record and extract that in the controller method. I'm finding that the form is posting everything (I might not be able to resolve that since the same form is used for updating). But I'd like to be able to have the variable pop into the parameter of controller method rather than extracting from the FormCollection. I've tried the various parameters below, but all are being passed null. Any idea what the problem is?
I have the following in my controller method:
public ActionResult Delete(FormCollection collection)
{
var idToDelete = collection["Current.CommissionStructureId"].ToInt32();
}
// tried the following but none of them bind
public ActionResult Delete(int? Current_CommissionStructureId, int? CommissionStructureId, int? Id, int? id)
{
// none of the above are binding (set to null)
}
You should use HttpPost only for deleting of records
#using (Html.BeginForm()) {
<input type="hidden" name="CommissionStructureId" value="#item.CommissionStructureId" />
<p>
<input type="submit" value="Delete" />
</p>
<p>
#Html.ActionLink("Back to List", "Index")
</p>
}
[HttpPost]
public ActionResult Delete(int CommissionStructureId)
{
CommissionStructure commissionStructure = db.CommissionStructures.Find(CommissionStructureId);
db.CommissionStructures.Remove(commissionStructure);
db.SaveChanges();
return RedirectToAction("Index");
}
When your form value is named Current.CommissionStructureId the default modelbinder will bind it only to a class parameter called Current with a property called Id.
So your options are
Create a small class with one property Id and use it as your parameter type
or
Write a custom modelbinder

Resources