I have a category and sub category dropdown list in my view. I select the items in the DDL and submit. In my controller I can only see the categoryID, subCategoryID values for the DDL. I need to get the selected text values (categoryName, subCategoryName). In winforms it is known as the DisplayMember.
I can get the categoryName, subcategoryName values if I run a query based on the returned ID, but this feels like I'm hitting the database more times than I need to.
Here is my code:
ViewModel
public class MedicalCategoryVM
{
public int PersonID { get; set; }
public int CategoryID { get; set; }
public string CategoryName { get; set; }
public int SubCategoryID { get; set; }
public string SubCategoryName { get; set; }
public string Notes { get; set; }
public Nullable<System.Guid> RowGuid { get; set; }
public Nullable<System.DateTime> ModifiedDate { get; set; }
public virtual Person Person { get; set; }
public List<MedicalCategory> MedicalCategories { get; set; }
}
View:
#model DofE.Models.MedicalCategoryVM
<br />
<br />
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="container">
#Html.Label("Medical Information", new { style = "font-size:16px; background-color:#002142; color:white;margin-left:10px" })
<div class="form-group">
#Html.DropDownListFor(model => model.CategoryID, new SelectList(Model.MedicalCategories,"CategoryID","CategoryName"),"--Select", new { #class = "form-control" })
</div>
<div class="form-group">
#Html.DropDownListFor(model => model.SubCategoryID, new SelectList(""), "--Select Sub Category", new { #class = "form-control" })
</div>
<div class="form-group">
<div class="row">
#Html.LabelFor(model => model.Notes, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Notes, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Notes, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="row">
#Html.LabelFor(model => model.PersonID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PersonID, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PersonID, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div style="padding-left:340px">
<span style="display: inline;">
#Html.ActionLink("Cancel", "Index", null, new { #class = "btn btn-danger btn-sm" }) <input type="submit" value="Create" class="btn btn-primary btn-sm" />
</span>
</div>
#*<div class="test">
<div style="float: right;">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</div>*#
</div>
</div>
}
<script src="~/Scripts/jquery-3.4.1.min.js"></script>
<script>
$(document).ready(function () {
$("#CategoryID").change(function () {
$.get("/MedicalHistory/GetSubCategoryList", { CategoryID: $("#CategoryID").val() }, function (data) {
$("#SubCategoryID").empty();
$.each(data, function (index, row) {
$("#SubCategoryID").append("<option value='" + row.SubCategoryID + "'>" + row.SubCategoryName + "</option>")
});
});
})
});
</script>
Controller:
public ActionResult Create()
{
MedicalCategoryVM CategoryVM = new MedicalCategoryVM();
CategoryVM.MedicalCategories = db.MedicalCategories.ToList();
//ViewBag.CategoryList = new SelectList(CategoryList, "CategoryID", "CategoryName");
return View(CategoryVM);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "PersonID,CategoryName,SubCategoryName,Notes,RowGuid,ModifiedDate")] MedicalHistory medicalHistory, FormCollection form)
{
//string catName = form["CategoryName"].ToString();
//string subCatName = form["SubCategoryName"].ToString();
int catID = Convert.ToInt16(form["CategoryID"]);
int subCatID = Convert.ToInt16(form["SubCategoryID"]);
MedicalSubCategory cat = db.MedicalSubCategories.Find(subCatID);
medicalHistory.CategoryName = cat.CategoryName;
medicalHistory.SubCategoryName=cat.SubCategoryName;
medicalHistory.RowGuid = Guid.NewGuid();
medicalHistory.ModifiedDate = DateTime.Now;
if (ModelState.IsValid)
{
db.MedicalHistories.Add(medicalHistory);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(medicalHistory);
}
Related
i m not able to solve one issue that is , there are two files one is uploaded at the form filled up for the first time and the other file will be uploaded when the form willl be edited , but the issue is that, when the first uploaded file is shown in edit and no changes be made, that files gets blank , i used exclude as well but that does not made any effect.
My Controller methods:
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
FileDetails fileDetails = db.FileUpload.Find(id);
if (fileDetails == null)
{
return HttpNotFound();
}
return View(fileDetails);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Exclude= "FileBeforeTour,FileBeforeTourName")] FileDetails fileDetails)
{
if (ModelState.IsValid)
{
string uploadedfilename = Path.GetFileName(fileDetails.fileaftertourupload.FileName);
if (!string.IsNullOrEmpty(uploadedfilename))
{
string filenamewithoutextension = Path.GetFileNameWithoutExtension(fileDetails.fileaftertourupload.FileName);
string extension = Path.GetExtension(fileDetails.fileaftertourupload.FileName);
string filename = filenamewithoutextension + DateTime.Now.ToString("yymmssfff") + extension;
fileDetails.FileAfterTourName = filename;
fileDetails.FileAfterTour = "~/Content/Files/" + filename;
filename = Path.Combine(Server.MapPath("~/Content/Files"), filename);
fileDetails.fileaftertourupload.SaveAs(filename);
db.Entry(fileDetails).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
}
return View(fileDetails);
}
My Edit View:
#model OnlineStationaryRegister.Models.FileDetails
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm("Edit", "File", FormMethod.Post, new { #enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>FileDetails</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.FileId)
<div class="form-group">
#Html.LabelFor(model => model.Officername, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Officername, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Officername, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Designation, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Designation, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Designation, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FileBeforeTour, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
View File
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FileAfterTour, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<input type="file" name="fileaftertourupload" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
My FileDetails model:
namespace OnlineStationaryRegister.Models
{
public class FileDetails
{
[Key]
public int FileId { get; set; }
public string Officername { get; set; }
public string Designation { get; set; }
public string FileBeforeTour { get; set; }
public string FileAfterTour { get; set; }
public string FileBeforeTourName { get; set; }
public string FileAfterTourName { get; set; }
public int status { get; set; } = 1;
[NotMapped]
public HttpPostedFileBase filebeforetourupload { get; set; }
[NotMapped]
public HttpPostedFileBase fileaftertourupload { get; set; }
}
}
It can be solved in many ways. One of the simplest ways as follows:
db.Entry(fileDetails).State = EntityState.Modified;
db.Entry(fileDetails).Property(x => x.FileBeforeTourName).IsModified = false; //<-- Here it is
db.Entry(fileDetails).Property(x => x.FileBeforeTour).IsModified = false; //<-- Here it is
db.SaveChanges();
I must not be searching with the correct phrases. This is a simple concept and I’ve done it in other languages and frameworks with ease.
I’m saving the UserID for the person who created the record and the UserID who last updated the record. Instead of displaying the UserID, I want to display the User.FirstName + ‘ ‘ + User.LastName.
The way I have it currently the LastEditBy and CreateBy is displayed on the page as blank.
Controller: I get the customer model and manually map the model to the customerViewModel then pass it to my partial view.
public ActionResult Edit(int customerId)
{
Customer customer = DbContext.Customers.FirstOrDefault(x => x.CustomerId == customerId);
CustomerViewModel customerViewModel = MapToViewModel(customer);
customerViewModel.UserSelectList = GetUserGroupList();
UserManager<ApplicationUser> _userManager = HttpContext.GetOwinContext().Get<ApplicationUserManager>();
var CreateByUser = _userManager.FindById(customerViewModel.CreateById);
var EditByUser = _userManager.FindById(customerViewModel.LastEditById);
customerViewModel.CreateBy = CreateByUser.FirstName + " " + CreateByUser.LastName;
customerViewModel.LastEditBy = EditByUser.FirstName + " " + EditByUser.LastName;
if (Request.IsAjaxRequest()) {
return PartialView("_CustomerEditPartial", customerViewModel);
}
return View("_CustomerEditPartial", customerViewModel);
}
The CustomerViewModel:
public class CustomerViewModel : DbContext{
public CustomerViewModel(): base("name=CustomerViewModel")
{
}
[Key]
public int CustomerId { get; set; }
[MaxLength(128), ForeignKey("ApplicationUser")]
public string UserId { get; set; }
public SelectList UserSelectList { get; set; }
#region additional Fields
// This overrides default conventions or data annotations
[Required(ErrorMessage = "Please enter your first name.")]
[StringLength(50)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Please enter your last name.")]
[StringLength(100)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime CreateDate { get; set; } = DateTime.Now;
public string CreateById { get; set; }
[NotMapped]
public string CreateBy { get; set; }
public string LastEditById { get; set; }
[NotMapped]
public string LastEditBy { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime LastEditDate { get; set; } = DateTime.Now;
public virtual ApplicationUser ApplicationUser { get; set; }
}
public class UserGroupList
{
public string Value { get; set; }
public string Text { get; set; }
}
My partial view page: _CustomerEditPartial.cshtml
#model WOA.ViewModels.CustomerViewModel
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" daa-dismiss="modal" aria-hidden="True">x</button>
<h4 class="modal-title">Edit Customer</h4>
</div>
#using (Ajax.BeginForm("Edit", "Customers", null, new AjaxOptions { HttpMethod = "Post", OnFailure = "OnFail" }, new { #class = "form-horizontal", role = "form" })) {
<div class="modal-body">
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.CustomerId)
<div class="form-group">
#Html.LabelFor(model => model.UserId, "UserId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.UserId, ViewData.Model.UserSelectList, "Select One", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.UserId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.LastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LastName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CreateDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.CreateDate, new { #readonly = "readonly" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CreateBy, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.CreateBy, new { #readonly = "readonly" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastEditBy, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.LastEditBy, new { #readonly = "readonly" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastEditDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.LastEditDate, new { #readonly = "readonly" })
</div>
</div>
</div>
</div>
<div class="modal-footer">
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" class="btn btn-primary" value="Save changes" />
</div>
</div>
</div>
<script type="text/javascript">
function OnSuccess() {
alert("success");
}
function OnFail() {
alert("fail");
}
function OnComplete() {
alert("Complete");
}
</script>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
</div>
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
I have updated my code, it is working now, however I do not believe it is the proper way to do this.
I believe I should be able to return the additional values I need via Linq on the initial call and not make two more trips to the database for the additional values.
I have not been able to figure out a way to make this work with Linq.
Thank you in advance for your time and effort.
I created a 2-dependent cascading dropdown list:
Model Classes
COUNTRIES
public int COUNTRY_ID { get; set; }
public string COUNTRY_NAME { get; set; }
STATES
public int STATE_ID { get; set; }
public Nullable<int> COUNTRY_ID { internal get; set; }
public string STATE_NAME { get; set; }
CITIES
public int CITY_ID { get; set; }
public Nullable<int> STATE_ID { internal get; set; }
public Nullable<int> COUNTRY_ID { internal get; set; }
public string CITY_NAME { get; set; }
The drop-down list worked as expected. But when clicked on save button, nothing is saved.
Controller: CITIES
// Json Call to get state
public JsonResult GetStates(string id)
{
List<SelectListItem> states = new List<SelectListItem>();
var stateList = this.Getstate(Convert.ToInt32(id));
var stateData = stateList.Select(m => new SelectListItem()
{
Text = m.STATE_NAME,
Value = m.STATE_ID.ToString(),
});
return Json(stateData, JsonRequestBehavior.AllowGet);
}
// Get State from DB by country ID
public IList<STATES> Getstate(int CountryId)
{
return _statesService.GetStates().Where(stat => stat.COUNTRY_ID == CountryId).ToList();
}
//
public ActionResult Create()
{
ViewBag.COUNTRIES = new SelectList(_countriesService.GetCountries(), "COUNTRY_ID", "COUNTRY_NAME");
ViewBag.STATES = new SelectList(_statesService.GetStates(), "STATE_ID", "state_NAME");
return View();
}
[HttpPost]
public ActionResult Create(CITIES cities)
{
try
{
IEnumerable<COUNTRIES> lstCountries = _countriesService.GetCountries();
if (ModelState.IsValid)
{
cities.ACTION_STATUS = 0;
cities.CREATED_DATE = DateTime.Now;
_citiesService.AddCity(cities);
return RedirectToAction("Index");
}
}
catch
{
ModelState.AddModelError("", "We cannot add this Cities. Verify your data entries !");
}
ViewBag.COUNTRIES = new SelectList(_countriesService.GetCountries(), "COUNTRY_ID", "COUNTRY_NAME", cities.COUNTRY_ID);
ViewBag.STATES = new SelectList(_statesService.GetStates(), "STATE_ID", "STATE_NAME", cities.STATE_ID);
return View(cities);
}
View : Cities
<div class=" box box-body box-primary">
#*#using (Html.BeginForm())*#
#using (Html.BeginForm("Create", "Cities", FormMethod.Post, new { #class = "form-horizontal", #enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, null, new { #class = "text-danger" })
<div class="row .col">
<div style="margin-top:20px" class="mainbox col-md-12 col-md-offset-0 col-sm-8 col-sm-offset-2">
<div class="panel panel-info">
<div class="panel-heading">
<div class="panel-title">Create City</div>
</div>
<div class="panel-body">
<div class="col-md-4">
<div>
#Html.LabelFor(model => model.COUNTRY_ID, "Country Name", new { #class = "control-label" })
#Html.DropDownList("COUNTRIES", ViewBag.COUNTRIES as SelectList, "-- Please Select a Country --", new { style = "width:250px" })
#Html.ValidationMessageFor(model => model.COUNTRY_ID, null, new { #class = "text-danger" })
</div>
</div>
<div class="col-md-4">
<div>
#Html.LabelFor(model => model.STATE_ID, "State Name", new { #class = "control-label" })
#Html.DropDownList("STATES", new SelectList(string.Empty, "Value", "Text"), "-- Please select a State --", new { style = "width:250px", #class = "dropdown1" })
#Html.ValidationMessageFor(model => model.STATE_ID, null, new { #class = "text-danger" })
</div>
</div>
<div class="col-md-4">
<div>
#Html.LabelFor(model => model.CITY_NAME, "City Name", new { #class = "control-label" })
#Html.TextBoxFor(model => model.CITY_NAME, new { #style = "border-radius:3px;", #type = "text", #class = "form-control", #placeholder = Html.DisplayNameFor(m => m.CITY_NAME), #autocomplete = "on" })
#Html.ValidationMessageFor(model => model.CITY_NAME, null, new { #class = "text-danger" })
</div>
</div>
</div>
<div class="panel-footer">
<div class="panel-title">
<div class="form-actions no-color">
<input type="submit" value="Create" class="btn btn-success" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
$(document).ready(function () {
//Country Dropdown Selectedchange event
$("#COUNTRIES").change(function () {
$("#STATES").empty();
$.ajax({
type: 'POST',
url: '#Url.Action("GetStates")', // Calling json method
dataType: 'json',
data: { id: $("#COUNTRIES").val() },
// Get Selected Country ID.
success: function (states) {
$.each(states, function (i, state) {
$("#STATES").append('<option value="' + state.Value + '">' +
state.Text + '</option>');
});
},
error: function (ex) {
alert('Failed to retrieve states.' + ex);
}
});
return false;
})
});
</script>
When I clicked on Countries Drop-down list, it populates and the respective states are loaded as expected. When I clicked on Save button, nothing is being saved. Please what is the problem
I'm pretty new to programming and I'm strugling with quite simple "Create" controller and view.
In the view user is declaring values, which should be passed to database. Here's the model:
public class Expense
{
public int ExpenseID { get; set; }
[DisplayName("Data")]
[Column(TypeName = "DateTime2")]
public DateTime Date { get; set; }
[DisplayName("Wartość")]
public decimal Amount { get; set; }
[DisplayName("Opis")]
public string Details { get; set; }
[DisplayName("Rodzaj")]
public int CategoryID { get; set; }
public virtual Category Category { get; set; }
}
public class Category
{
public int CategoryID { get; set; }
public string Name { get; set; }
public virtual ICollection<Expense> Expenses { get; set; }
}
In the same view I want to include partial view for managing the categories (adding, removing).
To have this working I've implemented ViewModel:
public class ExpenseCreateViewModel
{
public Expense ExpenseCreate { get; set; }
public Category CategoryCreate { get; set; }
}
And here's the code for my View:
#model Wydatki2._0.Models.ExpenseCreateViewModel
#{
ViewBag.Title = "Create";
}
<h2>Dodaj wydatek</h2>
<table class="table">
<tr>
<th>
<div>
#using (Html.BeginForm("CreateExpense", "ExpenseCreate", FormMethod.Post, new { }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.ExpenseCreate.CategoryID, "Rodzaj", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("CategoryID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.ExpenseCreate.CategoryID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ExpenseCreate.Amount, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ExpenseCreate.Amount, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ExpenseCreate.Amount, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ExpenseCreate.Date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ExpenseCreate.Date, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ExpenseCreate.Date, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ExpenseCreate.Details, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ExpenseCreate.Details, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ExpenseCreate.Details, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Dodaj" class="btn btn-default" />
</div>
</div>
</div>
}
</div>
</th>
<th>
<div>
<input type="button" id="btn" class="btn btn-default" value="Dodaj/Usuń Kategorię" />
<p class="error">#ViewBag.Warning</p>
</div>
<div id="Create" style="display:none">
#Html.Partial("CreateCategory", Model.CategoryCreate)
</div>
</th>
</tr>
</table>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/toggle")
}
The problem is that when I submit the form only the CategoryID value is passed correctly. The rest of parameters have just default values. The partial view is working well - I'm able to add or remove categories, which then are passed to the main view.
The code for my Controller:
namespace Wydatki2._0.Controllers
{
public class ExpenseCreateController : Controller
{
private WydatkiContext db = new WydatkiContext();
public ActionResult Create(bool? warn = false)
{
ExpenseCreateViewModel model = new ExpenseCreateViewModel()
{
ExpenseCreate = new Expense(),
CategoryCreate = new Category()
};
var query = from b in db.Categories
where b.CategoryID != 1
select b;
if (warn.GetValueOrDefault())
{
ViewBag.Warning = "Nie możesz usunąć tej kategorii.";
}
ViewBag.CategoryID = new SelectList(query, "CategoryID", "Name");
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateExpense([Bind(Include = "ExpenseID,Date,Amount,Details,CategoryID")] Expense expense)
{
if (ModelState.IsValid)
{
db.Expenses.Add(expense);
db.SaveChanges();
return RedirectToAction("Create");
}
var query = from b in db.Categories
where b.CategoryID != 1
select b;
ViewBag.CategoryID = new SelectList(query, "CategoryID", "Name", expense.CategoryID);
return View(expense);
}
public ActionResult CreateCategory()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateCategory([Bind(Include = "CategoryID,Name")] Category category)
{
if (ModelState.IsValid)
{
Category cat = db.Categories.FirstOrDefault(c => c.Name== category.Name);
if (cat != null)
{
if (cat.CategoryID == 1 || cat.CategoryID ==2)
{
return RedirectToAction("Create", new { warn = true });
}
else
{
db.Categories.Remove(cat);
db.SaveChanges();
return RedirectToAction("Create");
}
}
else
{
db.Categories.Add(category);
db.SaveChanges();
return RedirectToAction("Create");
}
}
return View(category);
}
I'm inclined to believe that the problem is caused by the model, which I'm passing to the view, but I really don't know, how to pass it correctly... Anyone could help with this?
You should use
([Bind(Prefix="prefixhere")]Category category)
I assume your prefix should be CategoryCreate for category, which the extension from your model ExpenseCreateViewModel, same for your CreateExpense, your prefix should be ExpenseCreate, this way you tell your controller to expect your input names after this prefix, so it will look for CategoryID and Name in create category action after the prefix you passed.
Something Like this
([Bind(Prefix="CategoryCreate")]Category category)
([Bind(Prefix="ExpenseCreate")]Expense expense)
When I tried to used debugger; in ajax to check if I'm able to serialize the form it say it is "undefined". I don't encounter an error but The value i input in the view does not pass to the controller. This is my reference https://stick2basic.wordpress.com/2013/04/14/how-to-pass-model-from-view-to-controller-using-jquery/
VIEW
<script type="text/javascript">
$(document).ready(function () {
$('#btnsubmit').click(function (e) {
e.preventDefault();
if ($("#OrderForm").valid()) { //if you use validation
$.ajax({
url: $("#OrderForm").attr('action'),
type: $("#OrderForm").attr('method'),
data: $("#OrderForm").serialize(),
success: function (data) {
alert("success");
}
});
}
});
});
</script>
#using (Html.BeginForm("_Order", "Account", FormMethod.Post, new { id = "OrderForm" }))
{
<div class="form-group">
<div class="col-md-3">
#Html.LabelFor(model => model.MerchantEmail, htmlAttributes: new { #class = "control-label col-md-2" })
</div>
<div class="col-md-9">
#Html.TextBoxFor(model => model.MerchantEmail, new { #Value = "abc#gmail.com",#class = "form-control" })
#Html.ValidationMessageFor(model => model.MerchantEmail, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="button" value="Create" id="btnsubmit" class="btn btn-primary" />
</div>
</div>
}
Controller
[AllowAnonymous]
[HttpPost]
public ActionResult _Order(OrderModel model)
{
List<OrderModel> orderlist = new List<OrderModel>();
if (Session["OrderList"] != null)
{
orderlist = Session["OrderList"] as List<OrderModel>;
orderlist.Add(model);
}
Session["OrderList"] = orderlist;
return PartialView();
}
MODEL
public class OrderModel
{
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[StringLength(35)]
public string FirstName { get; set; }
[StringLength(35)]
public string MiddleName { get; set; }
[StringLength(35)]
public string LastName { get; set; }
[StringLength(255)]
public string Address { get; set; }
[StringLength(40)]
public string Province { get; set; }
[StringLength(40)]
public string Town { get; set; }
[StringLength(13)]
public string MobileNo { get; set; }
[Required(ErrorMessage = "Please fill up Merchant Email.")]
[DataType(DataType.EmailAddress)]
public string MerchantEmail { get; set; }
[Required(ErrorMessage = "Please enter the exact amount.")]
[DataType(DataType.Currency)]
public float OrderAmount { get; set; }
public string OrderSkuCode { get; set; }
[Required(ErrorMessage = "Please fill up order details.")]
[StringLength(5000)]
public string OrderDetails { get; set; }
}
There are two things you are doing at the same time, you can have ajax or post the data directly to the controller.
#using (Html.BeginForm("_Order", "Account", FormMethod.Post, new { id = "OrderForm" }))
{
<div class="form-group">
<div class="col-md-3">
#Html.LabelFor(model => model.MerchantEmail, htmlAttributes: new { #class = "control-label col-md-2" })
</div>
<div class="col-md-9">
#Html.TextBoxFor(model => model.MerchantEmail, new { #Value = "abc#gmail.com",#class = "form-control" })
#Html.ValidationMessageFor(model => model.MerchantEmail, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="button" value="Create" id="btnsubmit" class="btn btn-primary" />
</div>
</div>
}
Here you are posting the data directly to the controller (Ajax is for Asynchronous Transfer) , this will by pass the Ajax request in the script.
If you want to post it through Ajax here is the code changes you need to do
<form id="form1">
<div class="form-group">
<div class="col-md-3">
#Html.LabelFor(model => model.MerchantEmail, htmlAttributes: new { #class = "control-label col-md-2" })
</div>
<div class="col-md-9">
#Html.TextBoxFor(model => model.MerchantEmail, new { #Value = "abc#gmail.com",#class = "form-control" })
#Html.ValidationMessageFor(model => model.MerchantEmail, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="button" value="Create" id="btnsubmit" class="btn btn-primary" />
</div>
</div>
</form>
<script type="text/javascript">
$(document).ready(function () {
$('#btnsubmit').click(function (e) {
e.preventDefault();
var data = new FormData($("#form1")[0]);
if ($("#OrderForm").valid()) { //if you use validation
$.ajax({
url: '#Url.Action("_Order","Your Controller Name")',
dataType: "json",
data: data,
success: function (data) {
alert("success");
}
});
}
});
});
</script>