TextAreaFor doesn't show default value (MVC4) - c#

I want to give my TextAreaFor a default value from my database (a certain comment which they can edit). I use the #Value and I can see it in the html code (inspect element), but in the textarea itself it isn't visible.
My code:
#Html.TextAreaFor(a => a.description, new { Value = ViewBag.Description }
ViewBag.Description = adver.description;

textarea works differently then other input fields in HTML and because of this the value attribute doesn't actually do anything that you'd expect.
<textarea value="you won't see this">you will see this</textarea>
Versus a text field:
<input type="text" value="you will see this" />
Because of this you need to assign the text that you want to be shown in the textarea to the variable before creating the textarea.
Edit
Here's a more complete example for you:
public ActionResult MyAction()
{
var myDefaultDescription = ""; //Replace with whatever you initialize ViewBag.Description with
return View(new AdverModel{ description = myDefaultDescription });
}
This will cause the model to be initialized in the controller. The #Html.TextAreaFor() only uses fields and values from the model object that's passed into the view. The Model variable is read only in the view so you must initialize it in the controller and pass it to the view during the return from the controller.
This will cause that field to auto populate with the default value.

Related

How to assign the value from an HTML Element as value of a variable defined in MVC Modal class in ASP.NET?

I am exploring CRUD Operations in MVC using ADO.Net in order to store the employee record and manipulate them as per necessity.
As I defined the table columns in Model, the MVC generates the view accordingly which generated HTML helper but not normal html elements. So now I have this html element:
<input type="text" id="datepicker">
This text box gets a string of datetime from the datepicker jQuery API. Now I have defined it in view model as
[Display(Name ="Travel Days")]
public string Date { get; set; }
Now I want to perform an operation to pass the value Date to the database. For this I have performed certain operations here:
public bool AddEmpInfo(EmpInfoModels Info)
{
using (connect = new SqlConnection(ConfigurationManager.ConnectionStrings["CrudMvc"].ToString()))
{
SqlCommand com = new SqlCommand("AddEmpInfo", connect);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#Date", Info.Date);
connect.Open();
int i = com.ExecuteNonQuery();
if (i >0)
{
return true;
}
else
{
return false;
}
}
}
As I debug the process, the value submitted from the view class is not received with the Info.Date.
So my problem is to bind the value entered from a plain html element and send it as a parameter to the stored procedure to perform database operations.
Add name to bind with Model
<input type="text" id="datepicker" name="Date">
MVC/Web Api Model binding can happen in three ways:
From Query string
Consider you are passing values in query string - http://your_domain/controller_name/youraction?id=100 - the id will be bound to your action parameter named "id", for eg, public ActionResult YourAction(int id).
You can even bind an object using query string values, for eg, url - http://your_domain/controller_name/youraction?id=100&name=your_name&age=30 & action public ActionResult YourAction([FromUrl]Employee employee) ,provided Employee class has id, name and age properties
From Route values - self explanatory, from the values you have specified in routes. In case of attribute routing, if we take the first scenario above, the action would look like:
[Route("YourAction/{id}')]
public ActionResult YourAction(int id)
From FormData - Putting it in simpler terms, when a form is submitted, model binder finds the elements whose name matches the property names and binds the value. For eg, if you want to bind an Employee object (which has Id, Name and Age properties) on form submit to an action, say,
[HttpPost]
public ActionResult YourAction(Employee employee)
you should have 3 html elements with the corresponding names like, <input type="text" name="Name" /><input type="hidden" name="Id" /> <input type="number" name="Age" />
This is exactly what #Html helpers do, they will assign the "name" attribute of the element to match the Model property.
So in your case, to bind value to "Date" property, you should have a html element with name="Date"

Default value of DropDownList in an Html.BeginForm block

While a search of "Default value of DropDownList" produces results, this is not a duplicate question because the specific issue is not listed in the examples and answers I have searched.
Here is the main question first, followed by supporting background and details:
When I place a DropdownList in an Html.BeginForm block, how can I have the default DropDownList values be an item other than the first item in the list?
What I have done so far:
SO, Microsoft Virtual Academy, and a general Internet Search using various search terms, with no effective answers that solve this specific issue.
Looking at the overloads of Html.DropDownList on MSDN. The optionLabel parameter inserts an item at the very top of the list, such as "Select an Item", which is not desired behavior.
jQuery, which does work as intended, but I'm really hoping there is a much simpler way that doesn't involve jQuery.
My Working Theory: The method I learned (and shown below) does not allow for default values and it is not a case of not knowing a particular overload of Html.DropDownList.
Background Info:
In the process of learning MVC 5 and gathering instructions from tutorials and SO answers, I learned this style of creating a DropDownList that is placed within a Html.BeginForm() block in the View. It works, if I want the default value to be the first item in the list or if I want to add an item inserted at the top that says "select an item."
However, there are times when it is meaningful to for the default value to be other than the first in the list.
In the controller, the defaults of the parameter are set Index(string campus = "MRA", string fy = "FY16"), and the query returns the correct result, but DropDownLists are not set accordingly when loading the page for the very first time.
Controller
public ActionResult Index(string campus = "MRA", string fy = "FY16")
{
/* The ViewBags feed DropDownLists used to filter the query */
ViewBag.CampusList = new List<string> { "CRA","DRA","MRA","PRA"};
ViewBag.FyList = new List<string> {"FY15","FY16" };
IEnumerable<AssociatedW3SuspensionOrProbation> query =
db.AssociatedW3SuspensionOrProbation
.Where(m=>m.Campus==campus).Where(m=>m.FY==fy)
.OrderBy(m=>m.StudentName).ThenBy(m=>m.LatestEntryDate);
return View(query.ToList());
}
View
The dropdowns function correctly: when the form is submitted, the query results are chosen by the selected dropdown values and the dropdowns load with the selected values.
#using (Html.BeginForm())
{
<div class="panel panel-default">
<div class="panel-body">
<p>
<strong>Campus</strong>: #Html.DropDownList("campus",
new SelectList(ViewBag.CampusList)) ||
<strong>FY</strong>: #Html.DropDownList("fy",
new SelectList(ViewBag.FyList))
</p>
<div><input type="submit" value="Search" /></div>
</div>
</div>
}
Is there a simple answer to this problem, or does this require a totally different approach?
What you have to do is create SelectList in the controller action and there is a constructor overload which can be used to set selected value, but for that you would need a List<T> which is not string but a custom type that contains 2 properties 1 for TextField and 1 for ValueField.
You have to use second Constructor overload listed here
Here is the example code:
ViewBag.CampusList = new SelectList(
new List<string> { "CRA","DRA","MRA","PRA"},
campus // selected value
);
ViewBag.FyList = new SelectList(
new List<string> {"FY15","FY16" },
,fy // selected value
);
and in your view:
#Html.DropDownList("campus",
ViewBag.CampusList as SelectList)
#Html.DropDownList("fy",
ViewBag.FyList as SelectList)

Different values from model

I have this two lines in a Razor template:
#Html.Hidden("step", Model.Step)
<p>#Html.Label(Model.Step.ToString())</p>
And they produce two different values:
<input data-val="true"
data-val-number="The field Step must be a number."
data-val-required="The Step field is required."
id="step"
name="step"
type="hidden"
value="0">
<p>
<label for="">1
</label>
</p>
How is this possible?
Property Step is of a type Int32 and is incremented every POST action.
EDIT:
#model ***.WebUI.Models.OrderViewModel
#{
ViewBag.Title = "New order";
}
<h2>
New order</h2>
#using (Html.BeginForm())
{
#Html.Hidden("step", Model.Step)
<p>#Html.Label(Model.Step.ToString())</p>
<div>
//other inputs
</div>
}
You have not shown you POST method, but based on "Property Step is of a type Int32 and is incremented every POST action." I assume it looks something like
public ActionResult Edit(OrderViewModel model)
{
model.Step = model.Step + 1;
return View(model);
}
When you post a model, the models values are added to ModelState (along with any ModelState errors) so in the first post, the ModelState value of Step will be 0. Html helpers use ModelState values for binding (if one exists) so when you return the view #Html.Hidden("step", Model.Step) will bind to the value of 0 (not the models value of 1). The reason for this behavior is explained in this answer.
The correct approach is to follow the PRG pattern (redirect to the GET method, passing a parameter indicating the Step value and initialize a new OrderViewModel), however you can make this work by clearing ModelState so that the Html Helper will use the model value.
public ActionResult Edit(OrderViewModel model)
{
ModelState.Clear(); // clear all model state
model.Step = model.Step + 1;
return View();
}
However, use this with caution. ModelState.Clear() removes all errors as well.

MVC 4 - hand over changed value from View to Controller

If a view is ment to allow editing of only one property but all other properties are being displayed (DisplayFor, non-editable) as well, what is a good way to design the handing-over of changed value to the controller?
Right now I have hidden-input-fields for all properties that are displayed with DisplayFor and the controller gets the full object passed.
This is pretty much ineffecient and I know it would suffice to post only the ID of that object and the changed value.
The user can input the value to be changed like this:
#Html.EditorFor(model => model.Verkaufspreis)
#Html.ValidationMessageFor(model => model.Verkaufspreis)
I could pass the ID of the object like this
#Html.ActionLink("Edit", "Edit", new { id=Model.ID })
But how would I pass the value that was changed? Thank you for your input.
if you want to get a value and you do not want to return the model knowing the name of the value you can use FormCollection
[HttpPost]
public ActionResult (FormCollectio collection)
{
string Verkaufspreis1=collection["Verkaufspreis"].ToString();
}
MVC allows all kinds of binding, for instance you could go
[HttpPost]
public ActionResult (int ID, String Verkaufspreis)
//Have to be the same propery name as your model
{
//Get original object with the ID
//change the "Sell of Stock" field
}
This would dynamically pass the ID and Verkaufspreis as parameters.
This would allow you to only have the ID and the value needing to be changed, as you would be getting the rest from your database(or wherever) on postback, only updating the value that is necessary.
You could do the entire model as a parameter, although this would mean you would have alot of empty values if you're not passing them to the client.
Instead of putting a lot of hidden inputs in your form, you can do this.
Simply post the changed values and the id to the action method. Read the full entity from your data source and update the new values and save it back.
[HttpPost]
public ActionResult Update(CustomerViewModel model)
{
Customer customer=repositary.GetCustomerFromID(model.ID)
customer.DisplayName=model.DisplayName;
repositary.SaveCustomer(customer);
return RedirectToAction("ProfileUpdated");
}
In this case, you need to post only the ID and DisplayName properties from the form
#model CustomerViewModel
<h2>Update Customer details</h2>
#using(Html.Beginform())
{
Display Name : #Html.TextBoxFor(x=>x.DisplayName)
#Html.HiddenFor(x=>x.ID)
<input type="submit" value="Save" />
}

Dynamically set Text and Value of TextBoxFor

I'm having a bit of an issue that I'd appreciate some help with.
I have a User object with properties ID and NAME that I need to display in a Readonly textbox. I'd like to populate the texbox's value with ID and Text with Name.
When submitted to Formcollection I need to retrieve entered data with:
collection.Get("User")
I know this is not the correct syntax but I'm trying to achieve the following:
#Html.TextBoxFor(model => model.User, new { #readonly="readonly",#Value = model.Id , #Text=model.Name })
What do I need to do to correct this ? In the textbox how can I display the user Name, when submitted return the user ID with collection.Get("User") ?
Thank you in advance.
p.s.
Standard
#Html.TextBoxFor(model => model.User.Name)
doesn't work for me as it doesn't store the value and
#Html.TextBoxFor(model => model.User, new { #readonly="readonly",#Value = Model.User.Id})
fails for obvious reason when User.Id is empty (in my case it's possible ).
You need to store the Id in a hidden input field.
#Html.HiddenFor(x => x.User.Id)
#Html.TextBoxFor(x => x.User.Name, new { #readonly = "readonly" })
Keep in mind that as long as you use readonly, the value will be model-binded. But as soon as the field is disabled, it won't. So you will receive null values in your Controller.
In the Controller you can use Modelbinding instead of accessing the FormCollection.
public ActionResult Whatever(User user)
{
// user.Id
// user.Name
// should be filled.
}
Update:
Why do you wan't to have those values in the view in the first place?
If you need them for modelbinding you should be aware that people are still able to manipulate them even though they are readonly (Firebug, POST requests from other scripts).
If you require them for your model to be valid I would recommend using hidden input fields. And on the server side make sure that you only save values that the user is actually supposed to change.

Categories