ASP.NET form field already have data - asp.net-mvc

I have 2 methods(actions) to create new "racun". Difference is, 1st one has dropdown list to choos kupac_id(FK),and the 2nd already has kupac_id sent by GET method. First one looks like this:
// GET: racuns/Create
public ActionResult Create()
{
ViewBag.kupac_id = new SelectList(db.kupacs, "id_kupac", "naziv");
return View();
}
// POST: racuns/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "id_racun,dv_racuna,status,dv_placanja,kupac_id")] racun racun)
{
if (ModelState.IsValid)
{
db.racuns.Add(racun);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.kupac_id = new SelectList(db.kupacs, "id_kupac", "naziv", racun.kupac_id);
return View(racun);
}
And the other one is like this:
// GET: racuns/CreateZaKupca
public ActionResult CreateZaKupca(int vid)
{
return View(new racun { kupac_id = vid });
}
// POST: racuns/CreateZaKupca
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateZaKupca([Bind(Include = "id_racun,dv_racuna,status,dv_placanja,kupac_id")] racun racun)
{
if (ModelState.IsValid)
{
db.racuns.Add(racun);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(racun);
}
So, when I run 1st action i got this -> http://prntscr.com/9k2cmc
And 2nd -> http://prntscr.com/9k2e56
Why is that, and can i get rid of those number and have empty field like in 1st action?
Ty for any help. EDIT:
<div class="form-group">
#Html.LabelFor(model => model.dv_racuna, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.dv_racuna, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.dv_racuna, "", new { #class = "text-danger" })
</div>
</div>
Part of code from view.

In your second action method, you are passing an object of your racun view model to the view and i am assuming that you have a property in this view model of type DateTime.
public class racun
{
public DateTime Datum_Racuna {set;get;}
}
And in your view, something like
#model racun
#using(Html.BeginForm())
{
#Html.EditorFor(s=>s.Datum_Racuna)
}
If you do not set the value of this property to a valid datetime, It will return you the DateTime.MinValue value(1/1/0001 12:00:00 AM), which is what you see in the form field.
If you wish to avoid this behaviour, you may change your property type from DateTime to Nullable DateTime(DateTime?).
public class racun
{
public DateTime? Datum_Racuna {set;get;}
}
Now since you changed the property type to nullable, you should do a null check before accessing the value to avoid Null Reference exceptions.
[HttpPost]
public ActionResult Create(racun model)
{
if(model.Datum_Racuna!=null)
{
var dtValue=model.Datum_Racuna.Value;
}
// to do :do something useful and return something useful.
}

Related

Remote Validation DropDownList MVC5

I want to Check whether the master type already exists or not using remote validation.
In my case the remote validation method is not firing.Can anyone help me?
Model
[Key, Column(Order = 1)]
[StringLength(200)]
[Display(Name = "MasterType")]
[Remote("IsNameAvailable", "MasterSetUps", ErrorMessage = "Master type already exists ")]
public string MasterType { get; set; }
Validation Method
[AllowAnonymous]
public JsonResult IsNameAvailable(string MasterType)
{
bool result = true;
if (s_mode == "ADD")
{
return Json(!db.MasterSetUps.Any(a => a.MasterType == MasterType), JsonRequestBehavior.AllowGet);
}
else if (s_mode == "EDIT" & MasterType != s_Master_Type_name)
{
return Json(!db.MasterSetUps.Any(a => a.MasterType == MasterType), JsonRequestBehavior.AllowGet);
}
return Json(result, JsonRequestBehavior.AllowGet);
}
View
<div class="form-group">
#Html.LabelFor(model => model.MasterType, htmlAttributes: new { #class = "control-label col-sm-2" })
<div class="col-sm-10">
#Html.DropDownList("MasterType", null, htmlAttributes: new { #class = "form-controls" })
#Html.ValidationMessageFor(model => model.MasterType, "", new { #class = "text-danger" })
</div>
</div>
GetMethod
public ActionResult Create()
{
s_mode = "ADD";
ViewBag.MasterType = new SelectList(db.Masters, "MasterType", "MasterType");
return View();
}
Your use of DropDownList(...) means that your not generating the necessary data-val-* attributes for validation. The method is using your ViewBag property for binding (not your model property) and their are no validation attributes associated with ViewBag.
Change the code in the GET method to
ViewBag.MasterTypeList = new SelectList (.....
and the view code to
#Html.DropDownListFor (m => m.MasterType, (SelectList)ViewBag.MasterTypeList, new { ... })
Note that the name of the property your binding to cannot be the same as the SelectList.

MVC 5 Multiselect List Values Not Binding to Model On Post

I have a view with several multiselect lists which are declared like this
<div class="col-md-6">
#Html.LabelFor(model => model.Counties, htmlAttributes: new { #class = "control-label" })
#Html.ListBoxFor(model => model.Counties, new MultiSelectList(ViewBag.CountyList, "Value", "Text"), htmlAttributes: new { #class = "form-control", size = 8, tabindex = 26 })
#Html.ValidationMessageFor(model => model.Counties, "", new { #class = "text-danger" })
<span class="small">Ctrl + click to select multiple items</span>
</div>
My view model contains a declaration like this:
public virtual List<long> Counties { get; protected set; }
My action looks like this:
[HttpPost]
public ActionResult Edit(TScholarshipView model, FormCollection form)
{
if (ModelState.IsValid)
{
TScholarship scholarship = Repo.GetScholarship(model.Id);
scholarship = Mapper.Map<TScholarshipView, TScholarship>(model, scholarship);
Repo.SaveOrUpdate(scholarship, HttpContext.User.Identity.Name);
return RedirectToAction("Edit", "AdminScholarship", new { id = model.Id });
}
return View("Scholarship", model);
}
On submit I can look at the post data sent by the browser and it is sending the appropriate data to the server
...&Counties=16&Counties=34&...
When the action begins to execute the value of Counties in the model is null. However I can look at the FormCollection values and the value of form["Counties"] is "16,34". Any ideas why the binding is not occurring?
I noticed this right after I posted the question. The problem was having the setter protected. This prevented the binder from setting the value of the list.
You need to reset the value of ViewBag.CountyList on post event as well.
Or have one property in the model and bind that property to your multi select list box.
Something like
Wrapper / Model
public class CustomerList
{
public List<Customer> Customers { get; set; }
public List<int> SelectedIDs { get; set; }
}
Controller
[HttpGet]
public ActionResult DisplayCustomer()
{
Customer oCustomer = new Customer();
List<Customer> CustomersList = new List<Customer>();
CustomersList.Add(new Customer() { ID = 1, Name = "TestCustomer1", Amt = 123 });
CustomersList.Add(new Customer() { ID = 2, Name = "TestCustomer2", Amt = 234 });
CustomersList.Add(new Customer() { ID = 3, Name = "TestCustomer3", Amt = 324 });
ViewBag.CustList = CustomersList;
return View(new CustomerList() { Customers = CustomersList });
}
[HttpPost]
public void DisplayCustomer(List<int> selectedIds)
{
// do something with the id list
}
View
#model MvcApplication2.Models.CustomerList
#using (Html.BeginForm(#Model.SelectedIDs))
{
#Html.ListBoxFor(m => m.SelectedIDs, new MultiSelectList(#Model.Customers, "ID", "Name", #Model.SelectedIDs))
<input type="submit" value="save" />
}
As mentioned here
Hope that works!!!

Why does the action method get wrong parameter?

I have the Action method and the View for editing properties of some items.
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Admin")]
public async Task<ActionResult> Edit(Item item)
{
if (ModelState.IsValid)
{
db.Entry(item).State = EntityState.Modified;
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
ViewBag.CatagorieId = new SelectList(db.Catagories, "ID", "Name", item.CatagorieId);
return View(item);
}
and
#model OpenOrderFramework.Models.Item
#using OpenOrderFramework.Extensions
#{
ViewBag.Title = "edit";
}
<h2>Editing</h2>
#using (Html.BeginForm())
{
<div class="form-horizontal">
<h4>The car</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.ID)
<-- etc -->
But when I submit the form I get an error
Store update, insert, or delete statement affected an unexpected number of rows (0).
I figured out that in action method ID of the item that was posted is always 0 even if real ID of the item is different.
Why does it happen?
GET Action method:
// GET: Items/Edit/5
[Authorize(Roles = "Admin")]
public async Task<ActionResult> Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Item item = await db.Items.FindAsync(id);
if (item == null)
{
return HttpNotFound();
}
ViewBag.CatagorieId = new SelectList(db.Catagories, "ID", "Name", item.CatagorieId);
return View(item);
}
When you post the form, the http call to your HttpPost action method is a totally separate Http request and Entity framework cannot track that entity.
As Darin mentioned in the comment, It is not a good idea to mix the entity classes in your UI layer. That makes it very tightly coupled.
What you should be using is creating and using a view model for your view. View model's are simply POCO classes, which is specific to the view.
public class ItemViewModel
{
public int Id {set;get;}
public string Name {set;get;}
public List<SelectListItem> Categories { set;get;}
public int SelectedCategory {set;get;}
}
And in your GET action, read the entity from your database,create an object of the view model and set the property values to that
public ActionResult Edit(int id)
{
var vm=new ItemViewModel { Id=id };
var item = db.Items.FirstOrDefault(s=>s.Id==id);
if(item!=null)
{
vm.Name = item.Name;
}
vm.Categories =db.Categories.Select(s=> new SelectListItem { Value=s.Id.ToString(),
Text=s.Name
}).ToList();
return View(vm);
}
And your view will be strongly typed to your view model
#model ItemViewModel
#using(Html.BeginForm())
{
#Html.DropdDownListFor(s=>s.SelectedCategory,Model.Categories,"Select")
#Html.HiddenFor(s=>s.Id)
#Html.TextBoxFor(s=>s.Name)
<input type="submit" />
}
And in your HttpPost action, read the existing entity from your db and update the property values you want to update.
[HttpPost]
public ActionResult Edit(ItemViewModel model)
{
if(ModelState.IsValid)
{
var item = d.Items.FirstOrDefault(s=>s.Id==model.Id);
item.Name = model.Name;
db.Entry(item).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
model.Categories =db.Categories.Select(s=>
new SelectListItem {
Value=s.Id.ToString(),
Text=s.Name }).ToList();
return View(model);
}
Make sure to add enough NULL checkings before accessing the entities/ objects in the code.

ASP.NET MVC Using DropDownLists

I am building a form using ASP.NET MVC which requires a drop-down list populated from a database.
I managed to get the drop-down list appearing, but no matter what I try to get the post data the application throws various errors.
In my Model:
public IEnumerable<SelectListItem> ApplicationTypeList { get; set; }
My Controller Get:
public ActionResult Create()
{
IEnumerable<SelectListItem> ApplicationTypeItems = Lists.ApplicationTypeList.Select(c => new SelectListItem { Value = c.Code, Text = c.Description });
ViewBag.AppTypes = ApplicationTypeItems;
return View();
}
Where c.Code is the value I want when the form is returned (string) and c.Description is just what is displayed.
The HttpPost Controller (auto-generated from scaffolding)
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include="PaymentID,ApplicationNumber,ApplicantName,ContactEmail,ContactAddress,ContactPhone")] Payment payment)
{
if (ModelState.IsValid)
{
db.Payments.Add(payment);
db.SaveChanges();
return RedirectToAction("Index");
}
return View();
}
For whatever reason it did not include ApplicationTypeList in the [Bind(Include=...
I also had to manually added this to the Create.cshtml View:
<div class="form-group">
#Html.LabelFor(model => model.ApplicationTypeList, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("ApplicationTypeList", (IEnumerable<SelectListItem>)ViewBag.AppTypes, "Please Select");
#Html.ValidationMessageFor(model => model.ApplicationTypeList)
</div>
</div>
When I submit the form I get the following error on the view:
There is no ViewData item of type 'IEnumerable' that
has the key 'ApplicationTypeList'.
I have looked around and tried a couple of other ways of generating the list such as including a new String APplicationTypeCode and creating the list using #Html.DropDownListFor(model => model.ApplicationTypeCode, Model.ApplicationTypeList); but still get errors.
What is the best method of working with a form that includes drop-down lists and returning the selected value to the application?
Thanks.
I suggest create viewmodel
public class InsertPaymentViewModel {
public SelectList ApplicationTypeList {get; set;}
// property for selected item
[Display(Name = "Display name")]
[Required]
public int ApplicationTypeSelectedCode {get; set;}
}
In Get action use this model (I don like ViewBag for complex forms)
public ActionResult Create()
{
var model = new InsertPaymentViewModel();
model.ApplicationTypeItems = new SelectList(Lists.ApplicationTypeList, "Code", "Description ")
return View(model);
}
View:
#model PathTo.ViewModels.InsertPaymentViewModel
<div class="form-group">
#Html.LabelFor(model => model.ApplicationTypeSelectedCode , new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.ApplicationTypeSelectedCode, model.ApplicationTypeItems , "Please Select");
#Html.ValidationMessageFor(model => model.ApplicationTypeSelectedCode)
</div>
</div>
HttpPost action
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(InsertPaymentViewModel model)
{
if (ModelState.IsValid)
{
var payment = new Payment
{
code = model.InsertPaymentViewModel; //or find reference by code...
// ... another property etc.
}
db.Payments.Add(payment);
db.SaveChanges();
return RedirectToAction("Index");
}
return View();
}

Pass Select into Controller via Response

Hy,
I'm new to ASP.NET MVC 5. I'm trying to get the value of an HTML select with no success.
My View (essential part):
<div class="form-group">
#Html.Label("Country", new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.DropDownList("Countries", (IEnumerable<SelectListItem>)ViewBag.Countries, new { #class = "form-control", id = "Country", name = "Country" })
</div>
</div>
My Controller (essential part):
public ActionResult Index()
{
string country = Request["Country"]; // here I always get null
}
I need a newbie like explanation why this is not working and how I get it to work, please :)
First, I agree with #Maess. Don't use ViewBag. It's horrible and someone at Microsoft should be slapped for ever adding it as an option in the first place.
That said, your error is pretty obvious here. You named your select "Countries" and you're trying to pull "Country" out of the request.
Since you're new, I'll be nice and lay out how to use a view model for this. First, create a model:
public class IndexViewModel
{
public int SelectedCountry { get; set; }
public IEnumerable<SelectListItem> CountryChoices { get; set; }
}
Then in your action:
// GET
public ActionResult Index()
{
var model = new IndexViewModel();
// get your country list somehow
// where `Id` and `Name` are properties on your country instance.
model.CountryChoices = countries.Select(m => new SelectListItem { Value = m.Id, Text = m.Name });
return View(model);
}
And in your view:
#model Namespace.IndexViewModel
...
#Html.DropDownListFor(m => m.SelectedCountry, Model.CountryChoices, new { #class = "form-control" })
And finally, in your POST action:
[HttpPost]
public ActionResult Index(IndexViewModel model)
{
// use model.SelectedCountry
}

Resources