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" />
Related
I need to do a calculator in ASP.NET MVC.
For the beginning I want to receive the value from the input field in controller and prefix it with the string "123". At the end I will process the expresion received and return the result.
I have the following model:
namespace CalculatorCloud.Models {
public class Calculator
{
public string nr { get; set; }
} }
In the view I am using the model:
#model CalculatorCloud.Models.Calculator
#{
ViewBag.Title = "Calculator";
}
#using (Html.BeginForm("Index", "Home"))
{
<div>
<div class="header">
#Html.TextBoxFor(m => m.nr, new { #id = "nr"})
<input type="button" id="C" name="C" value="C" />
<input type="button" id="back" name="back" value="<-" />
[...]
<div class="sum">
<input type="submit" value="=" />
</div>
</div>
}
The controller is like this:
namespace CalculatorCloud.Controllers
{
public class HomeController : Controller
{
Calculator model = new Calculator();
public ActionResult Index(string nr)
{
model.nr = "123" + nr;
return View(model);
}
}
}
I have the following problem: when pressing on submit button I am expecting to be displayed on the textbox the value from that was previously in the textbox, prefixed with the string "123".
But now it is kept the value from the textbox without the string "123".
Can someone help me with this?
Thank you! :)
If you want to modify the value of a model property in a postback action you will need to remove it from the ModelState:
public ActionResult Index(string nr)
{
ModelState.Remove("nr");
model.nr = "123" + nr;
return View(model);
}
The reason for this is that Html helpers such as TextBoxFor will first look at the value present in the ModelState and then in your view model property when rendering the value. This is by design.
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" />
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.
This is my view
<form method="post" action="/LoadCustomerAndDisplay/Search">
<fieldset>
<legend>Customer Book</legend>
<%= Html.Label("Name") %>
<%: Html.TextBox("Name") %>
<br />
<br />
<div>
<input type="submit" value="Sign" />
</div>
</fieldset>
</form>
This is my controller...
public ActionResult Search()
{
CustomerModels objCustomer = new CustomerModels();
var dataval = objCustomer.getData();
return View(dataval);
}
How can i get the value of Name textbox in the controller and pass it to the the getData like this....
var dataval = objCustomer.getData(ViewData['Name']);
this i put...showing error on fname....missing adding directive....what's the issue now...
<% Html.BeginForm("Search", "LoadCustomerAndDisplay");%>
<%: Html.TextBoxFor(m => m.fname) %>
<p>
<button type="submit">
Save</button></p>
<% Html.EndForm();%>
Use strongly typed view. In your GET action method, pass an object of your ViewModel to the view and use the HTML helper methods to create the input elements. When you submit the form, due to MVC model binding, you will get the values as the property values of the ViewModel in the POST action method.
Your GET action can stay same
public ActionResult Search()
{
CustomerModels objCustomer = new CustomerModels();
var dataval = objCustomer.getData();
// Assuming this method returns the CustomerViewModel object
//and we will pass that to the view.
return View(dataval);
}
so your View will be like
#model CustomerViewModel
#using (Html.BeginForm())
{
#Html.LabelFor(x=>x.Name)
#Html.TextBoxFor(x=>x.Name)
<input type="submit" value="Save" />
}
And have a POST action method to handle this
[HttpPost]
public ActionResult Search(CustomerViewModel model)
{
if(ModelState.IsValid)
{
string name= model.Name;
// you may save and redirect here (PRG pattern)
}
return View(model);
}
Assuming your objCustomer.getData() method in your GET Action method returns an object of CustomerViewModel which has a Name property like this
public class CustomerViewModel
{
public string Name { set;get;}
//other properties as needed
}
You can add a parameter to your Search action that accepts an object of Type CustomerModels. That way when you post something back to the controller, the model binder will take the data from the form and generate an object of type CustomerModels which you can then use in your action to work with. For that you need to do two things:
Your view should receive a model of type CustomerModels
Your action should be something like this public ActionResult Search(CustomerModels model)
If you don't want to change your view, that is, you don't want to pass model to your page, you could try and use TryUpdateModel inside your controller, or pass FormCollection object to your Search action and then query that collection.
In my Controller in a Asp.net MVC 1 app I want to use UpdateModel to populate a variable with POST data in my controller. I've looked at dozens of examples but even the most basic ones seem to fail silently for me.
Here's a very basic example that's just not working.
What am I doing wrong?
public class TestInfo
{
public string username;
public string email;
}
public class AdminController : Controller
{
public ActionResult TestSubmit()
{
var test = new TestInfo();
UpdateModel(test);//all the properties are still null after this executes
//TryUpdateModel(test); //this returns true but fields / properties all null
return Json(test);
}
}
//Form Code that generates the POST data
<form action="/Admin/TestSubmit" method="post">
<div>
<fieldset>
<legend>Account Information</legend>
<p>
<label for="username">Username:</label>
<input id="username" name="username" type="text" value="" />
</p>
<p>
<label for="email">Email:</label>
<input id="email" name="email" type="text" value="" />
</p>
<p>
<input type="submit" value="Login" />
</p>
</fieldset>
</div>
</form>
It looks like you're trying to get the controller to update the model based on the form elements. Try this instead:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult TestSubmit(TestInfo test)
{
UpdateModel(test);
return Json(test);
}
In your code, you're creating a new TestModel instead of letting the MVC runtime serialize it from the HttpPost. I've let myself get wrapped around the axel on this also, you're not the only one!
make properties of your public field:
public class TestInfo
{
public string username {get;set;}
public string email{get;set;}
}
I'm not too familiar with ASP.NET MVC, but shouldn't your TestSubmit method look more like this:
public ActionResult TestSubmit(TestInfo test)
{
UpdateModel(test);
return Json(test);
}
In the controller you should have two methods, one to respond to the GET, the other, if required is for responding to the POST.
So, firstly have a GET method:
public ActionResult Test ()
{
return View (/* add a TestInfo instance here if you're getting it from somewhere - db etc */);
}
Secondly, you'll need a POST method:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Test (TestInfo test)
{
return Json (test);
}
Notice that there's no UpdateMethod there, the ModelBinder would have done that for you.