I am using a Modal Partial View in my app. I am validating my model if it has errors I am returning the model using ModelState.AddModelError() but it is not working fine. Also, I could not load the SelectLists.
public ActionResult StockOut(StockOut model)
{
if (ModelState.IsValid)
{
var stock = (from s in db.Stocks where s.ProductId == model.ProductId select s).FirstOrDefault();
if (stock.Quantity > 0 && model.Quantity <= stock.Quantity)
{
var weight = ((from p in db.Products where p.Id == model.ProductId select p).FirstOrDefault().NetWeight) * model.Quantity;
stock.Quantity -= model.Quantity;
stock.TotalWeight -= weight;
StockOut entity = new StockOut()
{
DriverId = model.DriverId,
LastUpdated = DateTime.Now,
ProductId = model.ProductId,
Quantity = model.Quantity,
TotalWeight = weight
};
db.StockOut.Add(entity);
db.SaveChanges();
return RedirectToAction("Index");
}
else
{
ModelState.AddModelError("Quantity", "Please Enter A Valid Quantity");
ViewBag.ProductId = new SelectList(db.Products.ToList(), model.ProductId);
ViewBag.DriverId = new SelectList(db.Products.ToList(), model.DriverId);
}
}
ViewBag.ProductId = new SelectList(db.Products.ToList(), model.ProductId);
ViewBag.DriverId = new SelectList(db.Users.ToList(), model.DriverId);
return PartialView(model);
}
Before Submitting:
After Getting an Error
fix you select lists, you are creating them twice, remove one set (inside of if)
ViewBag.ProductId = new SelectList(db.Products.ToList(),"Id", "Name" , model.ProductId);
///Are you sure that you have have to use products again?
ViewBag.DriverId = new SelectList(db.Products.ToList(),"Id",
"Name" , model.DriverId);
and if you want to use AddModelError you have to add to form
#Html.ValidationSummary(false)
Related
In my ASP.NET MVC application, in the signup form, I want to check the user-entered values with my current database table and get the Id if a record is matched.
Here from the user's end, I'm getting their email address, surname, date of birth .
Then in the controller, I'm trying to match any record from the above details to get the existing record Id.
The issue is that it happens takes more time to run this query and returns as timeout.
Is there any way of searching the record more efficiently way?
This is my Controller code
public JsonResult SignUpCustomer(string emailAddress, string password, string surName, string name, DateTime dateOfBirth, string timeZone)
{
int customerId = 0;
try
{
customerId = db.Customer.AsEnumerable().Where(x => x.Sur_Name.ToLower().Contains(surName.ToLower()) && x.Date_of_birth.Date == dateOfBirth.Date && x.Email_Primary.ToLower() == emailAddress.ToLower()).Select(x => x.Id).FirstOrDefault();
if (customerId == 0) {
customerId = db.Customer.AsEnumerable().Where(x => x.Email_Primary.ToLower() == emailAddress.ToLower() && x.Date_of_birth.Date == dateOfBirth.Date).Select(x => x.Id).FirstOrDefault();
if (customerId == 0) {
customerId = db.Customer.AsEnumerable().Where(x => x.Sur_Name.ToLower().Contains(surName.ToLower()) && x.Date_of_birth.Date == dateOfBirth.Date).Select(x => x.Id).FirstOrDefault();
}
}
if (customerId != 0) {
UserAccounts accounts = new UserAccounts();
accounts.Email_Address = emailAddress;
accounts.Surname = surName;
accounts.Name = name;
accounts.Password = Crypto.Hash(password);
accounts.Status = true;
accounts.Created_Date = DateTime.UtcNow.AddMinutes(int.Parse(timeZone));
accounts.Customer_Id = customerId;
dbs.UserAccounts.Add(accounts);
dbs.SaveChanges();
} else {
UserAccounts accounts = new UserAccounts();
accounts.Email_Address = emailAddress;
accounts.Surname = surName;
accounts.Name = name;
accounts.Password = Crypto.Hash(password);;
accounts.Status = true;
accounts.Created_Date = DateTime.UtcNow.AddMinutes(int.Parse(timeZone));
accounts.Customer_Id = customerId;
dbs.UserAccounts.Add(accounts);
dbs.SaveChanges();
}
return Json(new {
Success = true,
}, JsonRequestBehavior.AllowGet);
} catch (Exception ex) {
throw;
}
}
You can clear your Linq query to something like this:
var loweredName=surName.ToLower();
var loweredEmailAddress=surName.ToLower();
var dateOfBirthDateDatePart=dateOfBirth.Date;
customerID = db.Customer.FirstOrDefault(
x => x.Sur_Name.ToLower().Contains(loweredName)
&& x.Date_of_birth.Year== dateOfBirthDateDatePart.Year
&& x.Date_of_birth.Month == dateOfBirthDateDatePart.Month
&& x.Date_of_birth.Day == dateOfBirthDateDatePart.Day
&& x.Email_Primary.ToLower() == loweredEmailAddress)?.Id;
Change other selects too.
Date comparison options are totally diffrenet depending on the version of Ef of efCore you are using. For choosing the best way check here
I want to populate my form fields using Spreadsheet data using Phone number. If the user entered their phone number, fields will be auto populated (Name, email, etc)
Now, its only populating the Full Name.
My Code.GS:
function autoComplete(info){
var opensheet = "https://docs.google.com/spreadsheets/d/xxxxxxxxx/edit#gid=0";
var sso = SpreadsheetApp.openByUrl(opensheet);
var wst = sso.getSheetByName("Invoices");
var data = wst.getRange(2, 1, wst.getLastRow()-1, 5).getValues();
var phoneSearch = data.map(function(r){ return r[0]; });
var newsletter = data.map(function(r){ return r[1]; });
var fullname = data.map(function(r){ return r[2]; });
var email = data.map(function(r){ return r[4]; });
var position = phoneSearch.indexOf(info);
if(position > -1){
return fullname[position];
} else {
return '';
}
}
My Javascript:
function getDetails(){
var info = document.getElementById("phone_number").value;
if(info.length === 14) {
google.script.run.withSuccessHandler(updateInfo).autoComplete(info)
}
}
function updateInfo(fullname){
document.getElementById("full_name").value = fullname;
M.updateTextFields();
}
I want to autocomplete the fields based on spreadsheet data. If user enters the phone number, the fields must be auto-filled up.
See screenshot: https://ibb.co/wJjz205
you might extend your script to return additional values in the object, like:
...
if(position > -1){
return {
'fullname': fullname[position],
'email': email[position]
// add other fields if necessary
}
} else {
return '';
}
...
and then access the vaules as the properties of returned object:
function updateInfo(response){
document.getElementById("full_name").value =response['fullname'];
document.getElementById("email").value =response['email'];
M.updateTextFields();
}
My function to pass roles to combobox in the custom form layout where the combobox is defined
private List<Role> GetRoles()
{
return db.Roles.ToList();
}
//this will pass a list of roles to the front end
ViewData["Roles"] = GetRoles();
Custom form layout this combox will then load a list of roles from the database table
#Html.DevExpress().ComboBox(ComboBoxsettings =>
{
Gsettings.Name = "Id";
ComboBoxsettings.Name = "RoleId";
ComboBoxsettings.Width = 500;
ComboBoxsettings.SelectedIndex = 1;
ComboBoxsettings.Properties.TextField = "Name";
ComboBoxsettings.Properties.ValueField = "Id";
ComboBoxsettings.Properties.DropDownStyle =
DropDownStyle.DropDown;
ComboBoxsettings.ShowModelErrors = true;
}
).BindList(ViewData["Roles"]).Render();
i am creating a form which can be accessed based on condition in MVC. I have first view with dropdownlist and submit button, i want when the submit button is clicked, the value in dropdownlist is passed and compared with condition set for that value, and if the condition is not ok, it shows alert rather than processing to the form.
Here is my code:
public ActionResult ChooseType()
{
var x = DataAccess.GetEmployee(#User.Identity.Name);
var lists = new SelectList(RuleAccess.GetAllRule(), "ID", "TypeDetail");
ViewBag.CategoryId = lists;
/*rule*/
ViewBag.comp1 = Logic.AnnualToogle(#User.Identity.Name);
if (x.EmpSex == "F" && x.EmpMaritalSt == "NIKAH")
{ ViewBag.comp2 = 1; }
else ViewBag.comp2 = 0;
return View();
}
[HttpGet]
public ActionResult Create(int lv_type)
{
var type = RuleAccess.GetTypeByID(lv_type);
ViewBag.type = type;
var model = new LeaveApplicationViewModels();
model.X = DataAccess.GetEmployee(#User.Identity.Name);
model.C = DataAccess.GetLeaveApp(#User.Identity.Name);
/*disable*/
ViewBag.dis = DataAccess.GetDisabledDate(#User.Identity.Name);
/*max*/
var max= RuleAccess.GetMaxByID(lv_type);
ViewBag.c = max;
if (lv_type == 1)
{
var used = RuleAccess.CountUsedAnnual(#User.Identity.Name);
var rem = max - used;
ViewBag.a = used;
ViewBag.b = rem;
}
else
{
ViewBag.b = max;
}
return View(model);
}
I used the Viewbag.comp 1 & 2 in my view:
<script type="text/javascript">
var x = #ViewBag.comp1;
var y = #ViewBag.comp2;
function validatecreate()
{
var value= document.getElementById("lv_type").value;
if (value==1)
{
if(x==1)
document.getElementById('validatecreate').submit();
else { alert('Action cant be done. You either have another annual leave application in pending status or you have reach the limit of annual leave'); }
}
else if(value==2)
{
if(y==1)
document.getElementById('validatecreate').submit();
else { alert('Action cant be done. You either are Male or Not Married Yet'); }
}
else if(value==3)
{
document.getElementById('validatecreate').submit();
}
else {
document.getElementById('validatecreate').submit();
//alert('Http Not Found');
}
}
#Html.DropDownList(
"lv_type", (SelectList) ViewBag.CategoryId,
"--Select One--",
new{ //anonymous type
#class = "form-control input-sm"
}
)
I feel like im doing it wrong especially because if someone manually put the url with ?lv_type=2, they not validate and can go to the form directly. But i need the value of lv_type bcs i use that in my view. Please Helpp :(
Validation must always be done on the server, and client side validation should only be considered a nice bonus that minimizes the need for to a call to the server. And presenting options in a dropdownlist to a user and then telling them thay can't select that option is an awful user experience. Instead, you should be presenting only those options which are applicable to the user (and delete all the scripts you have shown).
Create an additional method in your RuleAccess class, say GetEmployeeRules(Employee employee) which returns only the rules that are applicable to that employee, for example
public static List<Rule> GetEmployeeRules(Employee employee)
{
// Get the list of all rules
if (employee.EmpSex == "F" && employee.EmpMaritalSt == "NIKAH")
{
// Remove the appropriate Rule from the list
}
.....
// Return the filtered list
}
In addition, you should be using a view model in the view
public class LeaveTypeVM
{
[Required(ErrorMessage = "Please select a leave type")]
public int SelectedLeaveType { get; set; }
public IEnumerable<SelectListItem> LeaveTypeList { get; set; }
}
Then in the ChooseType() method
public ActionResult ChooseType()
{
var employee = DataAccess.GetEmployee(#User.Identity.Name);
var rules = RuleAccess.GetEmployeeRules(employee);
var model = new LeaveTypeVM()
{
LeaveTypeList = new SelectList(rules, "ID", "TypeDetail")
};
return View(model);
}
and in the view
#model LeaveTypeVM
#using (Html.BeginForm())
{
#Html.DropDownListFor(m => m.SelectedLeaveType, Model.LeaveTypeList, "--Select One--", new { #class = "form-control input-sm" }
#Html.ValidationMessageFor(m => m.SelectedLeaveType)
<input type="submit" value="Submit" />
}
and submit to a POST method which allows you to easily return the view if its invalid, or to redirect to the Create method.
[HttpPost]
public ActionResult ChooseType(LeaveTypeVM model)
{
if (!ModelState.IsValid)
{
model.LeaveTypeList = .... // as per GET method
}
return RedirectToAction("Create", new { leaveType = model.SelectedLeaveType });
and in the Create() method
public ActionResult Create(int leaveType)
{
var employee = DataAccess.GetEmployee(#User.Identity.Name);
var rule = RuleAccess.GetEmployeeRules(employee).Where(x => x.ID == leaveType).FirstOrDefault();
if (rule == null)
{
// Throw exception or redirect to an error page
}
var model = new LeaveApplicationViewModels();
....
return View(model);
}
Note your LeaveApplicationViewModels should contain additional properties so that you can avoid all those ViewBag properties and generate a strongly typed view.
I'm following this post
This is a simple application where administrators can prepare a questionnaire and prepare a simple survey and share it with whoever registered on our website.
Once the survey is completed by end users, the web site administrator (or whoever is authorized) can analyze the survey results and other feedback in any form like graphical or textual.
-- but there are some thing broken in it--
when you add a question you choose the type of question, so I made this class
public enum QuestionTypes
{
SingleLineTextBox, // will render a textbox
MultiLineTextBox, // will render a text area
YesOrNo, //will render a checkbox
SingleSelect, //will render a dropdownlist
MultiSelect //will render a listbox
}
and saved it in the database as a string but it renders in runtime in a different way ( the textbox ,SingleLineTextBox ,YesOrNo work well but MultiSelect and YesOrNo do not work )
This application uses entity framework - there is a section to add a question. It looks like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ddlTypes.Items.Add(QuestionTypes.SingleLineTextBox.ToString());
ddlTypes.Items.Add(QuestionTypes.MultiLineTextBox.ToString());
ddlTypes.Items.Add(QuestionTypes.SingleSelect.ToString());
ddlTypes.Items.Add(QuestionTypes.MultiSelect.ToString());
ddlTypes.Items.Add(QuestionTypes.YesOrNo.ToString());
}
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
SurveyAppConString context = new SurveyAppConString();
Question quest = new Question();
quest.Text = txtTitle.Text.Trim();
quest.QuestionType = ddlTypes.SelectedItem.Text;
quest.Options = txtValues.Text.Trim();
context.AddToQuestions(quest);
context.SaveChanges();
}
After that you can assign any question to survey and there's a page to display all surveys. It is broken there. I want to create a checkbox in run time and take his value as a string and save it in database and make the same thing with a listbox too
This is sample code ( works for textboxes and dropdownlist)
private void PopulateSurvey()
{
btnSubmit.Enabled = true;
List<Question> questions = (from p in context.Questions
join q in context.SurveyQuestions on p.ID equals q.QuestionID
where q.SurveyID == surveyid
select p).ToList();
Table tbl = new Table();
tbl.Width = Unit.Percentage(100);
TableRow tr;
TableCell tc;
TextBox txt;
CheckBox cbk;
DropDownList ddl;
foreach (Question q in questions)
{
tr = new TableRow();
tc = new TableCell();
tc.Width = Unit.Percentage(25);
tc.Text = q.Text;
tc.Attributes.Add("id", q.ID.ToString());
tr.Cells.Add(tc);
tc = new TableCell();
if (q.QuestionType.ToLower() == "singlelinetextbox")
{
txt = new TextBox();
txt.ID = "txt_" + q.ID;
txt.Width = Unit.Percentage(40);
tc.Controls.Add(txt);
}
if (q.QuestionType.ToLower() == "multilinetextbox")
{
txt = new TextBox();
txt.ID = "txt_" + q.ID;
txt.TextMode = TextBoxMode.MultiLine;
txt.Width = Unit.Percentage(40);
tc.Controls.Add(txt);
}
if (q.QuestionType.ToLower() == "singleselect")
{
ddl = new DropDownList();
ddl.ID = "ddl_" + q.ID;
ddl.Width = Unit.Percentage(41);
if (!string.IsNullOrEmpty(q.Options))
{
string[] values = q.Options.Split(',');
foreach (string v in values)
ddl.Items.Add(v.Trim());
}
tc.Controls.Add(ddl);
}
tc.Width = Unit.Percentage(80);
tr.Cells.Add(tc);
tbl.Rows.Add(tr);
}
pnlSurvey.Controls.Add(tbl);
}
You can quickly check the full code here and this is a database diagram:
note --
i worked in checkboxes area and added the code like that
i do the code like that
if (q.QuestionType.ToLower() == "yesorno")
{
lblyes = new Label();
lblyes.Text = "yes";
tc.Controls.Add(lblyes);
cbk = new CheckBox();
cbk.ID = "cbk_" + q.ID;
//cbk.value = "true";
cbk.Width=Unit.Percentage(41);
tc.Controls.Add(cbk);
}
// On Postback|Save
sres.Response = (ctrc as CheckBox).Checked ? "yes" : "no";
and it showed like that
it worked fine ( one checkbox )
to make two checkbox ( it's better to create aradiobutton)
i created and worked fine
if (q.QuestionType.ToLower() == "yesorno")//this is the name you create it when add anew question type
{
lblyes = new Label();
lblyes.Text = "yes";
tc.Controls.Add(lblyes);
rbk = new RadioButton();
rbk.ID = "rbk_" + q.ID;
rbk.GroupName = "rbyesno";
rbk.Width = Unit.Percentage(41);
tc.Controls.Add(rbk);
//add another chexbox and label
lblno = new Label();
lblno.Text = "no";
tc.Controls.Add(lblno);
rbk = new RadioButton();
rbk.ID = "cbk_1" + q.ID;
rbk.GroupName = "rbyesno";
rbk.Width = Unit.Percentage(41);
tc.Controls.Add(rbk);
}
// On Postback|Save
else if (ctrc is RadioButton)
{
//sres.Response = (ctrc as CheckBox).Checked.ToString();
sres.Response = (ctrc as RadioButton).Checked ? "no" : "yes";
}
We check on last radiobutton ( as created after the first one)
--- now i just need to create a list to select multiple choices from form and send it as a string to database
--- when i try to add alistbox so colud add a multible select quesion type to asurvey
this is asnippet of code
if (q.QuestionType.ToLower() == "MultiSelect")
{
lstmulti = new ListBox();
lstmulti.ID = "lst_" + q.ID;
lstmulti.Width = Unit.Percentage(41);
//lstmulti.Items.Add("on");
//lstmulti.Items.Add("sgsd");
//lstmulti.Items.Add("thre");
if (!string.IsNullOrEmpty(q.Options))
{
string[] values = q.Options.Split(',');
foreach (string v in values)
lstmulti.Items.Add(v.Trim());
}
tc.Controls.Add(lstmulti);
}
in save
else if (ctrc is ListBox)
{
//sres.Response = (ctrc as ListBox).SelectionMode.ToString();
sres.Response = (ctrc as ListBox).SelectedValue;
}
it didn't work at all
and it didn't render too as alistbox
//create list in run time
if (q.QuestionType.ToLower() == "MultiSelect")
{
ListBox lstmulti = new ListBox();
lstmulti.ID = "lst_" + q.ID;
lstmulti.Width = Unit.Percentage(41);
lstmulti.Height = Unit.Percentage(100);
lstmulti.SelectionMode = ListSelectionMode.Multiple;
//to select multible choices and send to database
if (lstmulti.SelectionMode == ListSelectionMode.Multiple)
{
var selected = new List<string>();
for (int i = 0; i < lstmulti.Items.Count; i++)
{
if (lstmulti.Items[i].Selected)
selected.Add(lstmulti.Items[i].Text);
string selectedItem = lstmulti.Items[i].Text;
//insert command
///it should send the result to databse where the table name is Survey_Response and column is Response
//SurveyAppConString db=new SurveyAppConString();
// //db.Survey_Response.Include(m => m.Response) = string.Join(",", selected);
}
}
if (!string.IsNullOrEmpty(q.Options))
{
string[] values = q.Options.Split(',');
foreach (string v in values)
lstmulti.Items.Add(v.Trim());
}
tc.Controls.Add(lstmulti);
}
//in post-save
else if (ctrc is ListBox)
{
//sres.Response = (ctrc as ListBox).SelectionMode.ToString();
sres.Response = (ctrc as ListBox).Items.ToString();
}
notes :: i'm using asp.net webform with entity framwork
For the listbox you'll have to set the SelectionMode to multiple and set the size to render. On postback if the SelectionMode is multiple then you will need to loop the items and concatenate the results.
if (myListBox.SelectionMode == SelectionMode.Multiple)
{
var selected = new List<string>();
foreach (var item in myListBox.Items)
if (item.Selected)
selected.Add(item.Text);
response = string.Join(",", selected);
}
You can easily follow the example and add a checkbox control with a "true" value. The issue is that unchecked checkboxes are not passed as form values so you could either set it to a default "false" if the form name does not exist in the form post, or you can set a hidden default value after the checkbox field and use the first passed value
Model binding in MVC will do this for you
https://stackoverflow.com/a/14731571/60669
Since the script is just looking at the Server controls its even simpler
if (q.QuestionType.ToLower() == "yesorno")
{
var cb = new Checkbox();
cb.Id = "cb_" + q.id;
cb.Value = "true;
// add to table cell
}
// On Postback|Save
if (ctrl is Checkbox)
{
sres.Result = (ctrl as Checkbox).Checked ? "true" : "false"
}
the listbox didn't render because of syntax error
in general the worked code are here
//create list in run time
if (q.QuestionType == "MultiSelect")
{
lstmulti = new ListBox();
lstmulti.ID = "lst_" + q.ID;
lstmulti.Width = Unit.Percentage(41);
lstmulti.Height = Unit.Percentage(100);
lstmulti.SelectionMode = ListSelectionMode.Multiple;
//to retrive the option values
if (!string.IsNullOrEmpty(q.Options))
{
string[] values = q.Options.Split(',');
foreach (string v in values)
lstmulti.Items.Add(v.Trim());
}
tc.Controls.Add(lstmulti);
}
tc.Width = Unit.Percentage(80);
tr.Cells.Add(tc);
tbl.Rows.Add(tr);
}
pnlSurvey.Controls.Add(tbl);
}
in save
else if (ctrc is ListBox)
{
var selected = new List<string>();
for (int i = 0; i < lstmulti.Items.Count; i++)
{
if (lstmulti.Items[i].Selected)
selected.Add(lstmulti.Items[i].Text);
string selectedItem = lstmulti.Items[i].Text;
sres.Response = string.Join(",", selected) ;
}
}
}