saving text box string value to database c# - c#

I have a textbox in which the user can enter their desired username and save it. Once they save it and they happen to revisit their profile page that textbox should be populated with the last username they saved to display and the user will still have the ability to change it and resave. I am fairly new to this and not sure how to start this properly. I am using vs 2012 asp.net mvc 4 c#. Here is my code so far:
#model School.Models.StudentNameModel
#using (Html.BeginForm("_StudentNamePartial", "Profile")) {
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<fieldset>
<ol>
<li>
#Html.LabelFor(m => m.StudentName)
#Html.DisplayFor(m => m.StudentName)
#Html.TextBoxFor(m=>m.StudentName)
<button type="button" value="save" />
</li>
</ol>
</fieldset>
}
This is my Model:
public class StudentNameModel
{
[Display(Name = "Student Name")]
public string StudentName{ get; set; }
}
My controller:
GET - To get the student name from database if one exists.
[HttpPost]
public ActionResult _StudentNamePartial(int id)
{
id = WebSecurity.CurrentStudentId;
var model = new StudentNameModel();
using (var db = new StudentsDataContext())
{
var result = (from u in db.Students
where u.ID == id
select u.StudentName).FirstOrDefault();
if(result != null)
model.StudentName= result;
}
return View(model);
}
POST - This is where i want to save the new username for the student
[HttpPost]
public ActionResult _StudentNamePartial(StudentNameModel model)
{
if (ModelState.IsValid)
{
using (var db = new StudentDataContext())
{
try
{
}
catch (Exception)
{
throw;
}
}
return RedirectToAction("ProfileAccount");
}
return View(model);
}
Also i am having trouble that when i am displaying the username it is not hitting my Action method and it always reports that the Object reference is null. Any help will be great. Thanks :D

It would seem that you're trying to render a partial view from a controller action as part of the larger view. In this case, the partial view should be rendered within the ProfileAccount view.
You can structure the controller and views like this (rough outline):
ProfileAccount View Model:
public class ProfileAccountView
{
public StudentNameModel StudentName { get; set; }
}
Profile Controller:
[HttpGet]
public ActionResult ProfileAccount(int id)
{
// Get whatever info you need and store in a ViewModel
var model = new ProfileAccountView();
// Get the student info and store within ProfileAccountView
// Do your database reads
model.StudentName = new StudentNameModel { StudentName = result };
return View(model);
}
[HttpPost]
public ActionResult ProfileAccount(ProfileAccountView profile)
{
// Do whatever processing here
}
ProfileAccount View
#model School.Models.ProfileAccountView
#using (Html.BeginForm("ProfileAccount", "Profile"))
{
#Html.RenderPartial('_StudentNamePartial', Model.StudentName);
<button type="button" value="save" />
}
_StudentNamePartial Partial View
#model School.Models.StudentNameModel
<fieldset>
<ol>
<li>
#Html.LabelFor(m => m.StudentName)
#Html.TextBoxFor(m=>m.StudentName)
</li>
</ol>
</fieldset>

Related

Why is my model failing validation

When I first load the page both my date textboxes are failing validation.
This appears to be because the two Date properties are set as required but are null.
My goals are to:
1) Have a model to pass into the controller that contains the criteria to search for.
2) That criteria will get reloaded when the page returns along with the results.
3) When the page 1st loads it will set the dates to a default to DateTime.Now and NOT show any results. When you submit the criteria it will then show results on next page load.
// Model
public class SearchModel
{
public long? StudentId { get; set; }
[Required]
public DateTime? Date1 { get; set; }
[Required]
public DateTime? Date2 { get; set; }
public List<string> Students { get; set; }
}
// View
#model SearchModel
<div>
#using (Html.BeginForm("StudentSearch", "Student", FormMethod.Post))
{
<span>
Date 1 #Html.TextBoxFor(m => m.Date1)
Date 2 #Html.TextBoxFor(m => m.Date2)
<input type="submit" value="Search" />
</span>
}
</div>
<div>
#foreach(var s in model.Students)
{ <span>#s</span> }
</div>
// Controller
[HttpGet]
public ActionResult StudentSearch(SearchModel model)
{
if (model.Date1 == null || model.Date2 == null)
{
model.Date1 = DateTime.Now;
model.Date2 = DateTime.Now;
}
return View();
}
Date time input is very sensitive. User could make a typo and ModelBinder won't be able to bind it to parameter. So, I suggest you to use framework like jQuery UI Datepicker or Kendo Datepicker.
public class StudentController : Controller
{
[HttpGet]
public ActionResult StudentSearch(SearchModel model)
{
if (model.Date1 == null || model.Date2 == null)
{
model.Date1 = DateTime.Now;
model.Date2 = DateTime.Now;
}
return View(model); <=====
}
[HttpPost]
public ActionResult StudentSearchPost(SearchModel model)
{
if (ModelState.IsValid)
{
// Do something
}
return View();
}
}
View
#model DemoWebMvc.Models.SearchModel
<div>
#using (Html.BeginForm("StudentSearchPost", "Student", FormMethod.Post))
{
<span>
Date 1 #Html.TextBoxFor(m => m.Date1)
Date 2 #Html.TextBoxFor(m => m.Date2)
<input type="submit" value="Search"/>
</span>
}
</div>
From Comment: I'm using a datetime picker control. Since the model
defaults to NULL since it's a DateTime? the very first page load shows
my date time fields failing validation. They're not failing because
what the user selects is invalid
The problem is you pass invalid model to View at Page Load, and default model binder tries to bind to model instance and it triggers validation error at Page Load.
If you do not have valid model, you should not send it to view at Page Load to avoid displaying validation error.
public class StudentController : Controller
{
[HttpGet]
public ActionResult StudentSearch()
{
return View();
}
[HttpPost]
public ActionResult StudentSearch(SearchModel model)
{
if (ModelState.IsValid)
{
}
return View(model);
}
}
View
#model DemoWebMvc.Models.SearchModel
#{
Layout = null;
}
#using (Html.BeginForm("StudentSearch", "Student", FormMethod.Post))
{
#Html.ValidationSummary(true)
<span>
Date 1 #Html.TextBoxFor(m => m.Date1)
#Html.ValidationMessageFor(m => m.Date1)<br />
Date 2 #Html.TextBoxFor(m => m.Date2)
#Html.ValidationMessageFor(m => m.Date2)<br />
<input type="submit" value="Search" />
</span>
}
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script>
$(function () {
$("#Date1").datepicker();
$("#Date2").datepicker();
});
</script>
Just changing the type from DateTime? to DateTime should accomplish what you want. You can set the value to DateTime.Now in the first action or leave it as the default unsigned. Either will work in the view.
Edit: Here's what I mean in a dotnetfiddle: https://dotnetfiddle.net/Ei0LeQ

Unable to bind ViewData to a dropdown list

I am working on an asp.net mvc 4 application where I am trying to add delete a user functionality for an admin where I should be able to select a user from dropdown list and delete him.
private static IEnumerable<SelectListItem> getUsers()
{
WhiteBoardAppContext db = new WhiteBoardAppContext();
IEnumerable<SelectListItem> numbers = (from i in db.UserProfiles
select new SelectListItem
{ Text= i.UserName,
Value=i.UserId.ToString()
});
return numbers.ToList();
}
[Authorize(Roles = "Admin")]
public ActionResult DeleteUser()
{
var list = (IEnumerable<SelectListItem>)ViewData["UserList"];
list = getUsers();
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Admin")]
public ActionResult DeleteUser(UserProfile model)
{
if (ModelState.IsValid)
{
try
{
if (model.UserName == null)
{
TempData["ErrorMessage"] = "Username required.";
return RedirectToAction("Register", "Account");
}
else
{
var user = Membership.GetUser(model.UserName);
if (user == null)
{
TempData["ErrorMessage"] = "User Does Not exist.";
return RedirectToAction("Register", "Account");
}
else
{
Membership.DeleteUser(model.UserName);
}
return RedirectToAction("Register", "Account");
}
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
DeleteUser.cshtml
#model WhiteBoardApp.Models.UserProfile
#using (Html.BeginForm("DeleteUser", "Account"))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<fieldset>
<div class="container-fluid">
<ol>
<li>
#Html.LabelFor(m => m.UserName)
#Html.DropDownList("UserList", (IEnumerable<SelectListItem>)ViewData["UserList"])
<span style="color:red;">#TempData["ErrorMessage"]</span>
</li>
</ol>
<input type="submit" value="Delete User" />
</div>
</fieldset>
}
But, the above code threw me There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'UserList'.
May I know where I was wrong?
You need to add your users to the ViewData dictionary:
[Authorize(Roles = "Admin")]
public ActionResult DeleteUser()
{
ViewData["UserList"] = getUsers();
return View();
}
Also your usage of DropDownList helper is wrong since the first parameter should be a name of input that is going to contain selected user and not a select list itself.
in your case var list = (IEnumerable<SelectListItem>)ViewData["UserList"]; will return null so there is no actual assignment.
But in general I would advise you not to use ViewData but create a VieModel and put all the required data there:
public class DeleteUserViewModel
{
public IList<SelectListItem> UserList {get;set;}
public int SelectedUserId {get;set;}
}
Controller :
[Authorize(Roles = "Admin")]
[HttpGet]
public ActionResult DeleteUser()
{
var model = new DeleteUserViewModel{
UserList = getUsers()
};
return View(model);
}
[HttpPost]
public ActionResult DeleteUser(DeleteUserViewModel model)
{
int userToDelete = model.SelectedUserId;
//delete user logic here
}
View:
#model WhiteBoardApp.Models.DeleteUserViewModel
#using (Html.BeginForm("DeleteUser", "Account"))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<fieldset>
<div class="container-fluid">
<ol>
<li>
#Html.LabelFor(m => m.UserName)
#Html.DropDownListFor(m=>m.SelectedUserId, Model.UserList )
<span style="color:red;">#TempData["ErrorMessage"]</span>
</li>
</ol>
<input type="submit" value="Delete User" />
</div>
</fieldset>
}

#Html.RadioButtonFor in mvc

In my application, my model contains a field id, and in the view I need to select an id with a radio button and post back the selected id to the controller. How can I do this? My view is as follows,
#model IList<User>
#using (Html.BeginForm("SelectUser", "Users"))
{
<ul>
#for(int i=0;i<Model.Count(); ++i)
{
<li>
<div>
#Html.RadioButtonFor(model => Model[i].id, "true", new { #id = "id" })
<label for="radio1">#Model[i].Name<span><span></span></span></label>
</div>
</li>
}
</ul>
<input type="submit" value="OK">
}
You need to change you model to represent what you want to edit. It needs to include a property for the selected User.Id and a collection of users to select from
public class SelectUserVM
{
public int SelectedUser { get; set; } // assumes User.Id is typeof int
public IEnumerable<User> AllUsers { get; set; }
}
View
#model yourAssembly.SelectUserVM
#using(Html.BeginForm())
{
foreach(var user in Model.AllUsers)
{
#Html.RadioButtonFor(m => m.SelectedUser, user.ID, new { id = user.ID })
<label for="#user.ID">#user.Name</label>
}
<input type="submit" .. />
}
Controller
public ActionResult SelectUser()
{
SelectUserVM model = new SelectUserVM();
model.AllUsers = db.Users; // adjust to suit
return View(model);
}
[HttpPost]
public ActionResult SelectUser(SelectUserVM model)
{
int selectedUser = model.SelectedUser;
}

how to get selected drow down list value in Action?

In MVC web app it is a view with strongly typed model where a drop down is being generated / bind by model.
Below is view code:
#model LoanViewModel
<form class="wrapper minheight homeloan-form border-top" id="homeloan-form" method="post" action="LeadContact" novalidate="novalidate">
<p>#Html.ValidationSummary()</p>
<p>Select an Item : #Html.DropDownListFor(x => x.HomeLoanLead.Items, new SelectList(Model.HomeLoanLead.Items), "--Choose any Item--")</p>
<div class="formnav row">
<button class="">Show Top Home Loans <i class="fa fa-chevron-right"></i></button>
</div>
</form>
In model I m hardcoding options for drop down list:
public List<string> Items
{
get { _items = new List<string>();
_items.Add("One");
_items.Add("Two");
_items.Add("Three");
return _items;
}
}
On post back I cant get what was selected value in drop down. Please guide me how to get in post action which drop down value was selected.
A simple example of using Html.DropDownFor() to display a list of options and bind to a property:
Model
public class LoanViewModel
{
[Required]
[Display(Name="Select Item")]
public string Item { get; set; }
public SelectList ItemList { get; set; }
}
Controller
public ActionResult Edit()
{
LoanViewModel model = new LoanViewModel();
model.Item = "Two"; // this will now pre-select the second option in the view
ConfigureEditModel(model);
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(LoanViewModel model)
{
if (!ModelState.IsValid)
{
ConfigureEditModel(model); // repopulate select list
return View(model); // return the view to correct errors
}
// If you want to validate the the value is indeed one of the items
ConfigureEditModel(model);
if (!model.ItemList.Contains(model.Item))
{
ModelState.AddModelError(string.Empty, "I'm secure!");
return View(model);
}
string selectedItem = model.Item;
....
// save and redirect
}
private void ConfigureEditModel(LoanViewModel model)
{
List<string> items = new List<string>() { "One", "Two", "Three" };
model.ItemList = new SelectList(items); // create the options
// any other common stuff
}
View
#model LoanViewModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.DisplayFor(m => m.Item)
#Html.DropDownListFor(m => m.Item, Model.ItemList), "--Choose any Item--")
#Html.ValidationMessageFor(m => m.Item)
<input type="submit" value="Submit" />
}

jQuery AutoComplete text not saving to db via create view using MVC3

This is my first post so please go easy on me fellas. I am trying to implement a create form that utilizes jquery autocomplete. The create form allows users to enter data that will be saved to my database, via a submit button. Here is my code:
Controller
// GET: /Inspection1/Create
public ActionResult Create()
{
InspectionInfo model = new InspectionInfo
{
Submitted = DateTime.Now,
Contact = new Contact()
};
ViewBag.CountyName = new SelectList(db.Counties, "CountyName", "CountyName");
return View(model);
}
//
// POST: /Inspection1/Create
[HttpPost]
public ActionResult Create(InspectionInfo inspectioninfo)
{
if (ModelState.IsValid)
{
db.InspectionInfos.Add(inspectioninfo);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(inspectioninfo);
}
// this allows for autocompletion behavior
public ActionResult QuickSearchContact(string term)
{
var contacts = db.Contacts
.Where(r => r.ContactName.Contains(term))
.Take(10)
.Select(r => new { label = r.ContactName });
return Json(contacts, JsonRequestBehavior.AllowGet);
}
Models
public class InspectionInfo
{
[Key]
public int InspectionId { get; set; }
[DataType(DataType.Date)]
public virtual DateTime Submitted { get; set; }
[DataType(DataType.MultilineText)]
[MaxLength(1000)]
public string Comments { get; set; }
[Required]
public Contact Contact { get; set; }
public class Contact
{
[Key]
public string ContactName { get; set; }
View:
<div class="editor-label">
#Html.LabelFor(model => model.Contact)
</div>
<div class="editor-field">
<input type ="text" name ="q" data-autocomplete=
"#Url.Action("QuickSearchContact", "Inspection")"/>
#Html.ValidationMessageFor(model => model.Contact.ContactName)
</div>
JS
$(document).ready(function () {
$(":input[data-autocomplete]").each(function () {
$(this).autocomplete({ source: $(this).attr("data-autocomplete")});
});
The autocomplete function seems to be working fine. It will pull column data from the database as I require. However, any data entered in the autocomplete text box, appears NULL in the database after the user has saved the form. Help here would be greatly appreciated.
For model binding to work, generally input names must match property names of your model. Surprisingly, you have named your input "q"
<input type ="text" name ="q" data-autocomplete="..."/>
Just rename it according to your model
<input type ="text" name="Contact.ContactName" data-autocomplete="..."/>
You don't have your on the code above but, instead of using
<input type ="text" name ="q" data-autocomplete= "#Url.Action("QuickSearchContact", "Inspection")"/>
use:
#EditorFor(x = x.NameOfTextBox)
then either have an input button wrapped in a using tag
#using (Html.BeginForm("Create", "NameOfController", FormMethod.Post){
//all your model stuff goes here
}
or use and actionlink instead of :
#Html.ActionLink("Submit", "Create", "NameOfController", Model)
The provided information doesn't tell, but is is likely that the autocomplete part is not written within the form elements of the view:
#using (Html.BeginForm())
{
<p>
...
</p>
}
In MVC the form is defined within the brackets { .... } like above.

Categories