Multiple Checkbox with Model returns null - asp.net-mvc

after I read data from my database, I try to show those datas in Html.Helper checkbox and I do that. But later when I try to get checked values back to the controller, model always returns null. Here's my controller part:
[HttpGet]
public ActionResult NewClient()
{
HizmetModel hizmetModel = new HizmetModel();
hizmetModel.hizmet = db.Hizmet.ToList<Hizmet>();
return View(hizmetModel);
}
[HttpPost]
public ActionResult NewClientPost(string name, string lastname, string telephone, string plate, HizmetModel hizmet)
{
Musteri musteri = new Musteri();
if (!db.Musteri.Where(x => x.plaka == plate).Any())
{
musteri.isim = name;
musteri.soyisim = lastname;
musteri.telefon = telephone;
musteri.plaka = plate;
db.Musteri.Add(musteri);
db.SaveChanges();
}
Islem islem = new Islem();
IslemHizmet islemhizmet = new IslemHizmet();
islem.giristarihi = DateTime.Now;
islem.plaka = plate;
var selectedHizmet = hizmet.hizmet.Where(x => x.isChecked == true).ToList<Hizmet>();
db.Islem.Add(islem);
db.SaveChanges();
var onprocessplate = db.Islem.Where(x => x.plaka == plate).FirstOrDefault();
foreach (var item in selectedHizmet)
{
islemhizmet.islem_id = onprocessplate.islem_id;
islemhizmet.hizmet_id = item.hizmet_id;
db.IslemHizmet.Add(islemhizmet);
db.SaveChanges();
islemhizmet = new IslemHizmet();
}
TempData["Success"] = "Müşteri başarıyla eklendi...";
return RedirectToAction("CurrentClients", "Admin");
}
This is my model for the list:
public class HizmetModel
{
public List<Hizmet> hizmet { get; set; }
}
I use this model in the cshtml file:
#model otoyikama.Models.Model.HizmetModel
And this is the loop for displaying checkboxes
#for (int i = 0; i < Model.hizmet.Count; i++)
{
<li>
<label>#Model.hizmet[i].hizmetisim</label>
#Html.CheckBoxFor(m => m.hizmet[i].isChecked)
#Html.HiddenFor(m => m.hizmet[i].hizmet_id)
#Html.HiddenFor(m => m.hizmet[i].hizmetisim)
</li>
}
I couldn't figure what's the problem here, my get action works fine, I can see all the data from database but I can't pass them back to controller.

As a first think , u need to create a object in your controller parameters such as like List<int> serviceIDs or List<Service> services so you can keep more data than one.
The html part:
#foreach(item in Model.Service)
{
<label>#item.ServiceName</label><br>
<input type="checkbox" name="services" value="#item.ServiceID">
<input type="hidden" name="services" value="#item.ServiceName">
}
The backend part:
[HttpPost]
public ActionResult NewClientPost(string name, string lastname, string telephone, string plate, List<Service> services)
{
}
when u do in that way, u will able to hold more services than to one and i think u can pass them the controller more easly.
when i face with that stuation, im taking those services ID's and calling them on the controller side like bellow;
The html part:
#foreach(item in Model.Service)
{
<label>#item.ServiceName</label><br>
<input type="checkbox" name="serviceIDs" value="#item.ServiceID">
}
The backend part:
[HttpPost]
public ActionResult NewClientPost(string name, string lastname, string telephone, string plate, List<int> serviceIDs)
{
List<Service> services= new List<Service>();
foreach(var item in serviceIDs)
{
var service=db.Service.Where(x => x.ServiceID == item).Any()
if(service.Count!=0)
{
services.Add(service);
}
}
}

Related

How to save changes of courses in EmployeeCourse table

What i Need
I need to save changes in courses in EmployeeCourse table
by remove all course for employee from EmployeeCourse table
then add courses after changes
Problem
when add changes in courses after remove i get error in save changes() function
{"An error occurred while updating the entries.
The INSERT statement conflicted with the FOREIGN KEY constraint
\"FK_EmployeeCourse_Course\". The conflict occurred in database \"mycourse\",
table \"dbo.Course\", column 'Id'.\r\nThe statement has been terminated."}
under submit button edit [httppost]
public ActionResult Edit(EditEmployeeVm model)
{
var emp = db.Employees.FirstOrDefault(f => f.Id == model.Id);
// remove all courses
foreach (EmployeeCourse eec in emp.EmployeeCourses.ToList())
{
var ec = db.EmployeeCourses.Find(eec.Id);
db.EmployeeCourses.Remove(ec);
}
// add courses again
foreach (var couseid in model.CourseIds)
{
db.EmployeeCourses.Add(new EmployeeCourse { CourseId = couseid, EmployeeId = emp.Id });
}
db.SaveChanges();
}
Debug result
debug add as image below
Details
Relation between two tables one to many
EmployeeCourse
Id(primary key) CourseId(forign key) EmployeeId(forign key)
Course table in database
Id(pk) CourseName
I using following view model for edit to get CourseIds
#model StudentCourses.Models.EditEmployeeVm
$(function () {
$(document).on("click", ".remove", function (e) {
e.preventDefault();
$(this).closest(".course-item").remove();
});
$('#AvailableCourses').change(function () {
var val = $(this).val();
var text = $("#AvailableCourses option:selected").text();
var existingCourses = $("input[name='CourseIds']")
.map(function () { return this.value; }).get();
if (existingCourses.indexOf(val) === -1) {
var newItem = $("<div/>").addClass("course-item")
.append(text + ' Remove ');
newItem.append('<input type="text" name="CourseIds" value="' + val + '" />');
$("#items").append(newItem);
}
});
});
</script>
to retrieve courses from database in edit view i used code below
<div>
#using (Html.BeginForm())
{
#Html.HiddenFor(g => g.Id)
#Html.LabelFor(f => f.Name)
#Html.DropDownList("AvailableCourses", Model.Courses, "Select")
<h4>Existing courses</h4>
<div id="items"></div>
foreach (var c in Model.ExistingCourses)
{
<div class="course-item">
#c.Name Remove
<input type="text" name="CourseIds" value="#c.Id" />
</div>
}
}
</div>
model used for that as following
public class EditEmployeeVm
{
public int Id { set; get; }
public List<SelectListItem> Courses { get; set; }
public int[] CourseIds { set; get; }
public List<CourseVm> ExistingCourses { set; get; }
}
public class CourseVm
{
public int Id { set; get; }
public string Name { set; get; }
}
}
update
public ActionResult Edit(int id)
{
var vm = new EditEmployeeVm { Id = id };
var emp = db.Employees.FirstOrDefault(f => f.Id == id);
vm.Name = emp.Name;
vm.ExistingCourses = db.EmployeeCourses
.Where(g => g.EmployeeId == id)
.Select(f => new CourseVm
{
Id = f.Id,
Name = f.Course.CourseName
}).ToList();
vm.CourseIds = vm.ExistingCourses.Select(g => g.Id).ToArray();
vm.Courses = db.Courses.Select(f => new SelectListItem
{
Value = f.Id.ToString(),
Text = f.CourseName
}).ToList();
return View(vm);
}
In your EDIT Get action, You are using the wrong id for CourseVm. It should be the Course Id, but you are setting the EmployeeCourse record/entity Id.
This should fix it.
vm.ExistingCourses = db.EmployeeCourses.Where(g => g.EmployeeId == id)
.Select(f => new CourseVm
{
Id = f.Course.Id,
Name = f.Course.CourseName
}).ToList();

How to pass model to partialview at run time?

ViewModel
public class ModelTypeViewModel
{
public virtual CheckRadioButton CRB { get; set; }
}
Controller
public class M1Controller : Controller
{
public CarContext db = new CarContext();
private CheckRadioButton get()
{
CheckRadioButton c = new CheckRadioButton();
c.BrandName = "abc";
c.type = "xyz";
return c;
}
public ActionResult Hello ()
{
CheckRadioButton s = get();
ModelTypeViewModel mm = new ModelTypeViewModel(s);
return View(mm);
}
View:(Hello)
#model Car.Models.ModelTypeViewModel
#Html.Partial("_Display", Model.CRB)
Partial View(_Display)
<h1> Hello </h1>
How can I pass diff model each time to to partial view?
It gives an error
"An exception of type 'System.Web.HttpParseException' occurred in System.Web.WebPages.Razor.dll but was not handled in user code"
It gives the same error even if I pass only 'Model"
I am confused
Put each button inside Ajax.BeginForm
#using (Ajax.BeginForm("BuyItem", "MsmqTest"}, new AjaxOptions { UpdateTargetId = "msmqpartial" }))
{ <button type="submit">Buy</button>}
#using (Ajax.BeginForm("BuyItem", "MsmqTest" }, new AjaxOptions { UpdateTargetId = "msmqpartial" }))
{
<button type="submit">Sell</button>
}
Where "updateTargetId" is the div id to append content
public ActionResult BuyItem()
{
if(//some condition goes here)
return PartialView("Partial1",data);
if(//some condition goes here)
return PartialView("Partial2",data);
}

Understanding how strongly typed html helper works

Framework: ASP.NET MVC 3
Tools: VS 2012
Hi guys,
I'm new to ASP.NET mvc, I have been using strongly typed html helper for some time,I don't understand them completely but know that it can provide type checking and keeps name according to property name,after using it for many times I faced this error constantly and dont seem to have any hint why its occuring tried several google searches but none helped me.
Error:
The name 'm' does not exist in the current context
Code:
#Html.LabelFor(m => m.OrginalCont.Title)
But this line of code works perfectly fine.
#Html.TextBox("origTitle", Model.OrginalCont.Title, new { #readonly = "", #class = "text-rounded", style = "width:425px" })
Can someone tell me whats going on here.I have used the same m => m.Name syntax several times in view but they are all working fine.
Update:
Alright I will try to post more code,but as the code may get too long I will try to keep it short and will post code which is related to the problem.
View
#model TS.MOP.Interface.Models.ProjectTranslationModel
<div class="form-item">
#Html.LabelFor(model => model.OrginalCont.Title)
<div class="editor-field">
#Html.TextBox("origTitle", Model.OrginalCont.Title, new { #readonly = "", #class = "text-rounded", style = "width:425px" })
</div>
</div>
Model
public class ProjectTranslationModel
{
public int ProjectId { get; set; }
[Required(ErrorMessageResourceType = typeof(Names), ErrorMessageResourceName = "Required_ErrorMessage")]
[DataType(DataType.Text)]
[Display(ResourceType = typeof(Names), Description = "TranslateLangs_Description", Name = "TranslateLangs_Title")]
public List<SelectListItem> TranslatableLangSelect { get; set; }
public TranslatableLanguageEditor TranslatableLangEditor { get; set; }
public OriginalContent OrginalCont { get; set; }
}
Controller
[Authorize]
public ActionResult TranslationEdit(int? id)
{
if (id.HasValue && User.IsInRole("ContentTranslator"))
{
var model = new ProjectTranslationModel();
model.ProjectId = id.Value;
var ContentTypeId = 2;//Project Page
Guid _currentUserId = Guid.Parse(Membership.GetUser(User.Identity.Name).ProviderUserKey.ToString());
var translatorSettings = db.TranslatorSettings.Where(x => x.UserId == _currentUserId).ToList();
model.TranslatableLangEditor = new TranslatableLanguageEditor();
var list = new List<SelectListItem>();
//Original Text
var originalContent = db.Projects.Where(x => x.Id == id.Value)
.Select(d => new OriginalContent { Title = d.Title, Content = d.Description, ContentCultureId = d.ProjectType.ContentCultureId }).FirstOrDefault();
model.OrginalCont = originalContent;
foreach (var item in translatorSettings)
{
//Select List
var li = new SelectListItem();
if (item.ContentCultureId != originalContent.ContentCultureId)//Dont add the Original Content CultureId to the dropDown
{
li.Value = item.ContentCultureId.ToString();
li.Text = item.ContentCulture.Description;
list.Add(li);
}
}
model.TranslatableLangSelect = list;
return View(model);
}
else
{
return View("Index");
}
}

ASP.NET MVC Postbacks and HtmlHelper Controls is not reflecting Model Changes

I'm facing problems with a MVC5 Razor web application. I have an authentication page (cshtml) that has an Id and password helper controls:
#model NetInfinity.Middleware.VistaModelos.LoginVistaModelo
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<h1>#Login.Acceso</h1>
<p>
#Html.TextBoxFor(c => c.Id, new { #placeholder = #Login.Usuario, autofocus = "", autocomplete = "off", maxlength = "15", size = "15" })
</p>
<p class="p1">
#Html.PasswordFor(c => c.Clave, new { #placeholder = #Login.Contraseña, maxlength = "20", size = "20" })
#Html.ActionLink(".", "Cambiopwd", null, new { #class = "login-cambiarpwd", id = "Cambiopwd" })
</p>
<p class="login-recordarpwd">#Html.ActionLink(#Login.RecordarPwd, "Recordatoriopwd")</p>
<button type="button" class="login-submit" id="login-submit">#Login.LoginSubmit</button>
}
And the respective Model:
public class LoginVistaModelo
{
public string Id
{
get;
set;
}
[DataType(DataType.Password)]
public string Clave
{
get;
set;
}
public string MensajeError
{
get;
set;
}
}
And Controller Action that validates user is:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginVistaModelo vmUsuario)
{
if (ModelState.IsValid)
{
EntidadesBD backend;
var cache = MemoryCache.Default;
backend = (EntidadesBD)cache.Get("backend");
if (backend == null)
{
backend = new EntidadesBD();
var politica = new CacheItemPolicy { Priority = CacheItemPriority.NotRemovable };
cache.Set("backend", backend, politica);
}
Usuario usuario = vmUsuario.ValidaUsuario();
if (usuario == null)
{
vmUsuario.MensajeError = "error2";
vmUsuario.Id = vmUsuario.Clave = String.Empty; // <--- This not works
ModelState.Clear(); // <-- This not works
}
else
{
}
}
return View(vmUsuario);
}
When Login Action is triggered to validate user and password and error is thrown, I need to clear TextBoxFor value and PasswordFor value, and to achieve this I set model properties Id and Clave to string.empty in Controller, however when page (cshtml) is rendered again, controls keep old values ignoring model changes, not even if ModelState.Clear(). I've heard that HtmlHelpers controls (like .TextBoxFor() etc.) don't bind to model values on Postback, but rather get their value directly out of the POST buffer from ModelState. Please, ¿How can I do to update controls value when they are changed in Model properties?
Thanks
try making the value of model null before returning it to view,
like vmUsuario.id = null, vmUsuario.clave= null ; and thn return the empty model to view
A better approach for this type of problem would be to redirect the user, rather than returning the view. Otherwise you run into the problem that if they press F5 it reposts the data. So simply redirect the user, and use TempData to include your error message. In your Get method, check if TempData contains an error message and display it if it does.

MVC checkboxes & FormCollection

On a mass-edit form page I display about 50 objects that have some boolean properties as well. The controller receives a FormCollection with all values from the edit page.
public void _EditAll(FormCollection c)
{
int i = 0;
if (ModelState.IsValid)
{
var arrId = c.GetValues("channel.ID");
var arrName = c.GetValues("channel.displayedName");
var arrCheckbox = c.GetValues("channel.isActive");
for (i = 0; i < arrId.Count(); i++)
{
Channel chan = db.Channels.Find(Convert.ToInt32(arrId[i]));
chan.displayedName = arrName[i];
chan.isActive = Convert.ToBoolean(arrCheckbox[i]);
db.Entry(chan).State = EntityState.Modified;
}
db.SaveChanges();
}
}
Now, for checkboxes, MVC creates hidden inputs on the form (otherwise "false" could not be posted back). In the controller, when receiving the FormCollection, this leads to the case that I receive an array of say
50 IDs,
50 names and ..
71 or so values for the checkboxes,
since the hidden checkbox has the same name as the visible one.
What's a good way to handle that and get the proper value of the checkbox?
Sample for editing array of entities that have boolean field.
Entity:
public class Entity
{
public int Id { get; set; }
public bool State { get; set; }
}
Controller:
public ActionResult Index()
{
Entity[] model = new Entity[]
{
new Entity() {Id = 1, State = true},
new Entity() {Id = 2, State = false},
new Entity() {Id = 3, State = true}
};
return View(model);
}
[HttpPost]
public ActionResult Index(Entity[] entities)
{
// here you can see populated model
throw new NotImplementedException();
}
View:
#model Entity[]
#{
using (Html.BeginForm())
{
for (int i = 0; i < Model.Count(); i++ )
{
#Html.Hidden("entities[" + i + "].Id", Model[i].Id)
#Html.CheckBox("entities[" + i + "].State", Model[i].State)
}
<input type="submit"/>
}
}
The only tricky thing is html elements naming.
More info about binding arrays.
I'm converting all arrays containing checkbox-values:
"false" => "false", if not preceded by "true"

Resources