asp.net web application hide data field at the backend - c#

I am making a web application and I used entity based EF designer from database model I want to hide modified by and modified Date for the backend and it shouldn't display to the user Can someone help how do I make this work? I have attached my picture and code below please let me know if there is any question.
Picture:
Controller CODE:
// GET: Contract
public ActionResult Index()
{
return View(db.Contracts.ToList());
}
// GET: Contract/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Contract contract = db.Contracts.Find(id);
if (contract == null)
{
return HttpNotFound();
}
return View(contract);
}
// GET: Contract/Create
public ActionResult Create()
{
return View();
}
// POST: Contract/Create
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
\[HttpPost\]
\[ValidateAntiForgeryToken\]
public ActionResult Create(\[Bind(Include = "Id,ContractName,ContractNumber,CreatedBy,CreatedDate,ModifiedBy,ModifiedDate")\] Contract contract)
{
if (ModelState.IsValid)
{
db.Contracts.Add(contract);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(contract);
}
// GET: Contract/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Contract contract = db.Contracts.Find(id);
if (contract == null)
{
return HttpNotFound();
}
return View(contract);
}
// POST: Contract/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
\[HttpPost\]
\[ValidateAntiForgeryToken\]
public ActionResult Edit(\[Bind(Include = "Id,ContractName,ContractNumber,CreatedBy,CreatedDate,ModifiedBy,ModifiedDate")\] Contract contract)
{
if (ModelState.IsValid)
{
db.Entry(contract).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(contract);
}
// GET: Contract/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Contract contract = db.Contracts.Find(id);
if (contract == null)
{
return HttpNotFound();
}
return View(contract);
}
// POST: Contract/Delete/5
\[HttpPost, ActionName("Delete")\]
\[ValidateAntiForgeryToken\]
public ActionResult DeleteConfirmed(int id)
{
Contract contract = db.Contracts.Find(id);
db.Contracts.Remove(contract);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
`
I tried to figure out but I don't know how to hide these two modified date and modified by at the backend.
View code
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Contract</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.ContractName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ContractName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ContractName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ContractNumber, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ContractNumber, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ContractNumber, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CreatedBy, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CreatedBy, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CreatedBy, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CreatedDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CreatedDate, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CreatedDate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ModifiedBy, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ModifiedBy, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ModifiedBy, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ModifiedDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ModifiedDate, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ModifiedDate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button style="background-color:white; border-color:darkgrey;"><input type="submit" value="Create" class="btn btn-default" /></button>
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
<script src="~/Scripts/jquery-3.4.1.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

Often times the entity types stored in the database have fields you don't want to, can't, or shouldn't expose on the UI.
If you're not concerned about the data being present and would just like to "hide" it, simply don't include those in the table markup.
If however you don't want the fields present at all, a common way to get around that is to create a DTO class that only has the fields you wish to expose. Update your UI to target the DTO and remove the columns from the table.
public class ContractDto
{
// all the fields you want to expose
// Ctor
public ContractorDto(Contract contract) { ... }
// "From" pattern
public static ContractDto From(Contract contract)
=> new ContractDto { ... }
// An implicit operator can also be helpful
public static implicit operator ContractDto(Contract contract)
=> new ContractDto { ... }
}
If you need to update the fields you dropped after an update for example, load the entity type using the primary key and update it. This assumes you have some way to populate the current user.
var entity = db.Contracts.Find(contractDto.Id);
// update entity from dto as needed
entity.ModifiedBy = // populate the user from context or similar
entity.ModifiedDate = DateTime.Now;

Related

Issue With Login and Registration in asp.net mvc?

I m a student I m Learning MVC.
I have only one table for login and registration.
problem is login is not working as well as registration is not work
stanstuds.cs
public class stanstuds
{
[Key]
public int id { get; set; }
public string fname { get; set; }
public string mname { get; set; }
public string lname { get; set; }
public string country { get; set; }
public string usertype { get; set; }
public string username { get; set; }
public string password { get; set; }
}
context class
public class stanstudcontext:DbContext
{
public stanstudcontext():base("cnnos")
{
}
public DbSet<stanstuds> studs { get; set; }
}
controller
public class LogRegController : Controller
{
stanstudcontext context = new stanstudcontext();
//admin view just I print the sample message this is an admin view
public ActionResult Index()
{
return View();
}
//client view just I print the sample message this is a client view
public ActionResult Clientview()
{
return View();
}
//Login
[HttpGet]
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(stanstuds studs)
{
var userdata=context.studs.Where(x => x.username == studs.username && x.password == studs.password).FirstOrDefault();
if (userdata != null) //when i m debugging this condition is not check
{
// i have a 2 records of admin in database but when i run time enter that record login is not working
/// if (userdata.usertype == "admin")
//{
// return RedirectToAction("Index", "LogReg");
//}
//else
//{
// return RedirectToAction("Clientview", "LogReg");
//}
//}
/else
//{
// return View();
//}
if (userdata != null)
{
if (userdata.password == userdata.password) //success
{
//here give an error httpsessionstatebase does not contain a definition for setint32 and no extension method setnt32 are u missing directive or assembly reference???
HttpContext.Session.SetInt32("id", userdata.id);
if (userdata.usertype == "admin")
return RedirectToAction("Index", "LogReg");
else
return RedirectToAction("Clientview", "LogReg");
}
else
{
ViewBag.Message = "Invalid Password!";
return View();
}
}
else
{
ViewBag.Message = "Invalid Email!";
return View();
}
}
//Registration
public ActionResult Regis()
{
return View();
}
[HttpPost]
public ActionResult Regis(stanstuds studs)
{
context.studs.Add(studs);
context.SaveChanges();
return View();
}
}
Login.cshtml
#model LoginRegOneTable.Models.stanstuds
#{
ViewBag.Title = "Login";
}
<h2>Login</h2>
<html>
<head>
<title>Demo Website</title>
</head>
<body>
#using (Html.BeginForm())
{
<div>
<label>UserName:</label>
#Html.EditorFor(model => model.username)
</div>
<div>
<label>Password:</label>
#Html.EditorFor(model => model.password)
</div>
<div>
<input type="submit" value="Login" />
</div>
}
</body>
</html>
Regis.cshtml
#{
ViewBag.Title = "Regis";
}
<h2>Regis</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>stanstuds</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.fname, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.fname, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.fname, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.mname, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.mname, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.mname, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.lname, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.lname, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.lname, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.country, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.country, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.country, "", new { #class = "text-danger" })
</div>
</div>
**I think the problem is here I want to insert by default entry as a user but how???**
<div class="form-group">
#Html.LabelFor(model => model.usertype, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.usertype, new { htmlAttributes = new { #class = "form-control" ,#value = "User"} })
#Html.ValidationMessageFor(model => model.usertype, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.username, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.username, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.username, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.password, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.password, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.password, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
when user registration then insert by default entry as a user my registration is not working when I press register button then the record is not inserted and when I press login then login is not working? something is wrong my script?? please help??
In this case, you can check if the typed password is equal to the password in database, and check if it works:
var userdata = context.studs.Where(x => x.username.Equals(studs.username)).FirstOrDefault();
if (userdata != null)
{
if (userdata.Password == userdata.Password) //success
{
HttpContext.Session.SetInt32("id", userdata.id);
if (userdata.usertype == "admin")
return RedirectToAction("Index", "LogReg");
else
return RedirectToAction("Clientview", "LogReg");
}
else
{
ViewBag.Message = "Invalid Password!";
return View();
}
}
else
{
ViewBag.Message = "Invalid Email!";
return View();
}

How to realize Edit method with 2 models in 1 View

The beginning of my topic is here.
Using DropDownList dont allow me to edit Author`s name.. But that solution is really good.
I need to edit all 4 fields like name, title, year and price.
I try to make something like composite model:
public class BookAuthorCompositeModel
{
public Author author { get; set; }
public Book book { get; set; }
}
Change my get method:
// GET: Books/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return HttpNotFound();
}
var compModel = new BookAuthorCompositeModel();
compModel.book = dbBooks.Books.ToList().Where(a => a.Id == id).SingleOrDefault();
compModel.author = dbBooks.Authors.ToList().Where(x => x.Id == id).SingleOrDefault();
return View(bookEdit);
}
and it displays all I need (i tap "edit" and see information about name, title, year and price).
My view is:
#model BookStorage.Models.BookAuthorCompositeModel
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Book</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.book.Id)
<div class="form-group">
#Html.LabelFor(model => model.author.AuthorName, "AuthorName", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.author.AuthorName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.author.AuthorName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.book.Title, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.book.Title, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.book.Title, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.book.YearPublish, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.book.YearPublish, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.book.YearPublish, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.book.Price, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.book.Price, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.book.Price, "", new { #class = "text-danger" })
</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")
}
but something wrong is in Post method:
[HttpPost]
public ActionResult Edit(Book book)
{
if (ModelState.IsValid)
{
dbBooks.Entry(BAmodel.book).State = EntityState.Modified;
dbBooks.Entry(BAmodel.author).State = EntityState.Modified;
dbBooks.SaveChanges();
return RedirectToAction("Index");
}
return View(book);
}
dbBooks.SaveChanges(); leads to error (Store update, insert, or delete statement affected an unexpected number of rows (0).). I think using this kind of ViewModel helps to edit all rows, but it doesn't send data to DB, and I can't understand what is wrong.
If I understood correctly, what you want is to update a context "Book" and a context "Author" at the same API method.
To do so, first I would make a ViewModel that contains both objects, which you already have:
public class BookAuthorCompositeModel
{
public Author author { get; set; }
public Book book { get; set; }
}
(This can be modified for validation purposes, maybe creating new objects for validation. At least, I did it like that. But let's go on.)
Now, you need to receive that same ViewModel on your API call, and then do what you need with the objects. To do so, I usually do a Get call on my context, obtaining the object to be modified. Then I'm free to update my context:
[HttpPost]
public ActionResult Edit(BookAuthorCompositeModel model)
{
...
}
To get the object to be modified, depends on what you are using. Simple repository pattern, Unit pattern, doesn't matter. When you get the Book entry, just modify it, use Update function, which I belive to be dbBooks.BookContext.Update(book), where "book" is variable. Something like this:
var book = dbBooks.BooksContext.Get(model.Book.BookId);
book.name = "New Name";
dbBooks.BooksContext.Update(book);
dbBooks.SaveChanges();
The method for getting and updating ( .Get() and .Update() ) must be the ones from the pattern that you are using, but maybe this can help you.
Good luck!

Razor populating drop down list

On my page I want to include a list of members in a drop down list but I am not sure how exactly I could do this.
How would I populate a drop down list with the members that I am passing with the controller?
This is my controller
//Add Event
public ActionResult CreateEvent()
{
var members = db.ClubMembers.ToList();
return View(members);
}
//Add Event
[HttpPost]
public ActionResult CreateEvent(ClubEvent incomingEvent)
{
try
{
if (ModelState.IsValid)
{
using (var db = new UltimateDb())
{
db.ClubEvents.Add(incomingEvent);
db.SaveChanges();
}
return RedirectToAction("Index");
}
return View();
}
catch
{
return View();
}
}
This is the view I will be using
#model ultimateorganiser.Models.ClubEvent
#{
ViewBag.Title = "CreateEvent";
}
<h2>CreateEvent</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>ClubEvent</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#*Event Title*#
<div class="form-group">
#Html.LabelFor(model => model.EventTitle, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.EventTitle, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.EventTitle, "", new { #class = "text-danger" })
</div>
</div>
#*Event Description*#
<div class="form-group">
#Html.LabelFor(model => model.EventDesc, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.EventDesc, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.EventDesc, "", new { #class = "text-danger" })
</div>
</div>
#*Event Type*#
<div class="form-group">
#Html.LabelFor(model => model.eventType, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EnumDropDownListFor(model => model.eventType, htmlAttributes: new { #class = "form-control", #id = "dropdown" })
#Html.ValidationMessageFor(model => model.eventType, "", new { #class = "text-danger" })
</div>
</div>
#*Add People*#
#*<div class="form-group">
Add Members
<div class="col-md-10">
Drop Down List of members will go here
</div>
</div>*#
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
The best way to pass data between views and action methods are view models.We will go that way.
First create a new view model for the create view.
public class CreateEventVm
{
public string EventDescription {set;get;}
public List<SelectListItem> Members {set;get;}
public int MemberId {set;get;}
}
and in your GET action
public ActionResult Create()
{
var vm = new CreateEventVm();
var db= new UltimateDb();
vm.Members =db.Members.Select(s=> new SelectListItem
{ Value=s.Id.ToString(),
Text = s.Name
}).ToList();
return View(vm);
}
And your create razor view which is strongly typed to our new CreateEventVm
#model CreateEventVm
#using(Html.BeginForm())
{
<label>Description</label>
#Html.TextBoxFor(s=>s.EventDescription)
<label>Member</label>
#Html.DropDownListFor(s=>s.MemberId,Model.Members,"Select one")
<input type="submit" />
}
And in your HttpPost action method
[HttpPost]
public ActionResult Create(CreateEventVm model)
{
if(ModelState.IsValid)
{
using (var db = new UltimateDb())
{
var event = new ClubEvent();
event.EventDescription = model.EventDescription;
//Set other properties also from view model.
db.ClubEvents.Add(event);
db.SaveChanges();
}
// Redirect to another action after successful save (PRG pattern)
return RedirectToAction("SavedSuccessfully");
}
vm.Members =db.Members.Select(s=> new SelectListItem
{ Value=s.Id.ToString(),
Text = s.Name
}).ToList();
return View(vm);
}

razor mvc5 c# web for input slider range

I'm trying to get a range slider input on my c# mvc 5 view page that i can submit the input to the mvc controller to write to a database. i tried using Jquery Ui Slider but i couldn't figure how to get the values over to my c# code for writing form data to database.
here's the view cshtml file
#model RateMyCourse.ReviewCourse
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>ReviewCourse</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Review, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Review, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Review, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Relevance, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Relevance, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Relevance, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Fun, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Fun, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Fun, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Difficulty, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Difficulty, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Difficulty, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Clarity, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Clarity, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Clarity, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Rating, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Rating, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Rating, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Like, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Like, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Like, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Dislike, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Dislike, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Dislike, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CourseCourseId, "CourseCourseId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("CourseCourseId", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.CourseCourseId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.User_UserId, "User_UserId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("User_UserId", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.User_UserId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
and here's the Controller file
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using RateMyCourse;
namespace RateMyCourse.Controllers
{
public class ReviewCoursesController : Controller
{
private CollegeRocksEntities db = new CollegeRocksEntities();
// GET: ReviewCourses
public ActionResult Index()
{
var reviewCourse = db.ReviewCourse.Include(r => r.Course).Include(r => r.User);
return View(reviewCourse.ToList());
}
// GET: ReviewCourses/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
ReviewCourse reviewCourse = db.ReviewCourse.Find(id);
if (reviewCourse == null)
{
return HttpNotFound();
}
return View(reviewCourse);
}
// GET: ReviewCourses/Create
public ActionResult Create()
{
ViewBag.CourseCourseId = new SelectList(db.Course, "CourseId", "Name");
ViewBag.User_UserId = new SelectList(db.User, "UserId", "UserName");
return View();
}
// POST: ReviewCourses/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ReviewCourseId,Review,Relevance,Fun,Difficulty,Clarity,Rating,Like,Dislike,CourseCourseId,User_UserId")] ReviewCourse reviewCourse)
{
if (ModelState.IsValid)
{
db.ReviewCourse.Add(reviewCourse);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CourseCourseId = new SelectList(db.Course, "CourseId", "Name", reviewCourse.CourseCourseId);
ViewBag.User_UserId = new SelectList(db.User, "UserId", "UserName", reviewCourse.User_UserId);
return View(reviewCourse);
}
// GET: ReviewCourses/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
ReviewCourse reviewCourse = db.ReviewCourse.Find(id);
if (reviewCourse == null)
{
return HttpNotFound();
}
ViewBag.CourseCourseId = new SelectList(db.Course, "CourseId", "Name", reviewCourse.CourseCourseId);
ViewBag.User_UserId = new SelectList(db.User, "UserId", "UserName", reviewCourse.User_UserId);
return View(reviewCourse);
}
// POST: ReviewCourses/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ReviewCourseId,Review,Relevance,Fun,Difficulty,Clarity,Rating,Like,Dislike,CourseCourseId,User_UserId")] ReviewCourse reviewCourse)
{
if (ModelState.IsValid)
{
db.Entry(reviewCourse).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CourseCourseId = new SelectList(db.Course, "CourseId", "Name", reviewCourse.CourseCourseId);
ViewBag.User_UserId = new SelectList(db.User, "UserId", "UserName", reviewCourse.User_UserId);
return View(reviewCourse);
}
// GET: ReviewCourses/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
ReviewCourse reviewCourse = db.ReviewCourse.Find(id);
if (reviewCourse == null)
{
return HttpNotFound();
}
return View(reviewCourse);
}
// POST: ReviewCourses/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
ReviewCourse reviewCourse = db.ReviewCourse.Find(id);
db.ReviewCourse.Remove(reviewCourse);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
Most likely you have missed one of these:
a) does my element in view has corresponding name
<input type="number" class="nmbr" name="second"/>
b) have I included my wanted element in bindings list
public ActionResult Create([Bind(Include = "second")] ReviewCourse reviewCourse)
these 2 are most likely reasons. And if still it is missing, check if you are actually posting all the data.

View model using its value between actions in mvc

I have a problem which I cant figure out how to fix. please note I'm very new to MVC.
Im designing a survey which has 8 questions. Im creating each question in a view.
What I need to is to keep the data between my views, but I lose the data even though I passed them through as a single view model.
Please help....
I have the following ViewModel
public class SurveyViewModelNew
{
public string description { get; set; }
public Question1ViewModel QuestionText1 { get; set; }
public Question2ViewModel QuestionText2 { get; set; }
public Question3ViewModel QuestionText3 { get; set; }
public Question4ViewModel QuestionText4 { get; set; }
public Question5ViewModel QuestionText5 { get; set; }
public Question6ViewModel QuestionText6 { get; set; }
public Question7ViewModel QuestionText7 { get; set; }
public Question8ViewModel QuestionText8 { get; set; }
}
And a view Model for each question:
public class Question1ViewModel
{
public string QuestionText { get; set; }
public AnswerViewModel Answers { get; set; }
}
and I here is how my view look like ?
#model survey.Models.SurveyViewModelNew
#using (Html.BeginForm("QuestionOneNext", "CreateSurveyStep2", FormMethod.Post, new { #class = "form-horizontal", role = "form", Model = Model }))
{
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.Label("Question 1: What question would you like to ask", htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-5">
#Html.EditorFor(model => model.QuestionText1.QuestionText, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.QuestionText1.QuestionText, "", new { #class = "text-danger" })
</div>
</div>
<br/>
<br/>
<div class="form-group">
#Html.Label("Answer A", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.QuestionText1.Answers.AnswerTextA, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.QuestionText1.Answers.AnswerTextA, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.Label("Answer B", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.QuestionText1.Answers.AnswerTextB, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.QuestionText1.Answers.AnswerTextB, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.Label("Answer C", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.QuestionText1.Answers.AnswerTextC, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.QuestionText1.Answers.AnswerTextC, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.Label("Answer D", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.QuestionText1.Answers.AnswerTextD, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.QuestionText1.Answers.AnswerTextD, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.Label("Answer E", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.QuestionText1.Answers.AnswerTextE, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.QuestionText1.Answers.AnswerTextE, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.Label("Answer F", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.QuestionText1.Answers.AnswerTextF, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.QuestionText1.Answers.AnswerTextF, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.Label("Answer G", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.QuestionText1.Answers.AnswerTextG, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.QuestionText1.Answers.AnswerTextG, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.Label("Answer H", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.QuestionText1.Answers.AnswerTextH, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.QuestionText1.Answers.AnswerTextH, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.Label("Answer K", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.Label("Not applicable", htmlAttributes: new { #class = "control-label col-md-2" })
</div>
</div>
<div class="form-group">
#Html.Label("Answer L", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.Label("Flag inappropriate question/refuse to answer", htmlAttributes: new { #class = "control-label col-md-5" })
</div>
</div>
<br/>
<br/>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Previous Step" class="btn btn-info" name="direction"/>
<input type="submit" value="Add a New Question to this survey" class="btn btn-danger" name="direction" />
<input type="submit" value="Countinue to submit this survey" class="btn btn-success" name="direction" />
</div>
</div>
</div>
}
and here is how my controller look like:
[HttpPost]
public ActionResult QuestionOneNext(SurveyViewModelNew surveyViewModel, string direction)
{
if (direction == "Countinue to submit this survey")
return RedirectToAction("Edit", "something", surveyViewModel);
if (direction == "Add a New Question to this survey")
{
return View("QuestionTwo", surveyViewModel);
//return RedirectToAction("QuestionTwo", "CreateSurveyStep2", surveyViewModel);
}
if (direction == "Previous Step")
return RedirectToAction("Index", "CreateSurveyStep1", surveyViewModel);
return View();
}
[HttpPost]
public ActionResult QuestionTwo(SurveyViewModelNew surveyViewModel, string direction)
{
if (direction == "Countinue to submit this survey")
{
return RedirectToAction("Edit", "NutStorage", surveyViewModel);
}
if (direction == "Add a New Question to this survey")
{
//return RedirectToAction("QuestionThree", "CreateSurveyStep2", surveyViewModel);
return View("QuestionThree", "CreateSurveyStep2", surveyViewModel);
}
if (direction == "Previous Step")
return RedirectToAction("QuestionOne", "CreateSurveyStep2", surveyViewModel);
return View();
}
what happens is when I get to "QuestionTwo" action in my controller I lose the answer to the first question.
I fixed this by using TemData, the following is my fixed controller:
[HttpGet]
public ActionResult QuestionOne(SurveyViewModelNew surveyViewModel)
{
var currentSurveyViewModel = (SurveyViewModelNew)TempData["SurveyView"];
if (currentSurveyViewModel != null)
{
if (currentSurveyViewModel.description != null)
{
surveyViewModel.description = currentSurveyViewModel.description;
}
if (currentSurveyViewModel.QuestionText1 != null)
{
surveyViewModel.QuestionText1 = currentSurveyViewModel.QuestionText1;
}
if (currentSurveyViewModel.QuestionText2 != null)
{
surveyViewModel.QuestionText2 = currentSurveyViewModel.QuestionText2;
}
if (currentSurveyViewModel.QuestionText3 != null)
{
surveyViewModel.QuestionText3 = currentSurveyViewModel.QuestionText3;
}
if (currentSurveyViewModel.QuestionText4 != null)
{
surveyViewModel.QuestionText4 = currentSurveyViewModel.QuestionText4;
}
if (currentSurveyViewModel.QuestionText5 != null)
{
surveyViewModel.QuestionText5 = currentSurveyViewModel.QuestionText5;
}
if (currentSurveyViewModel.QuestionText6 != null)
{
surveyViewModel.QuestionText6 = currentSurveyViewModel.QuestionText6;
}
if (currentSurveyViewModel.QuestionText7 != null)
{
surveyViewModel.QuestionText7 = currentSurveyViewModel.QuestionText7;
}
TempData["SurveyView"] = surveyViewModel;
}
if (surveyViewModel.description!= null)
{
surveyViewModel.description = surveyViewModel.description;
TempData["SurveyView"] = surveyViewModel;
}
return View("QuestionOne", surveyViewModel);
}
[HttpGet]
public ActionResult QuestionOneNext(SurveyViewModelNew surveyViewModel, string direction)
{
var currentSurveyViewModel = (SurveyViewModelNew)TempData["SurveyView"];
if (currentSurveyViewModel != null)
{
if (currentSurveyViewModel.description != null)
{
surveyViewModel.description = currentSurveyViewModel.description;
}
if (currentSurveyViewModel.QuestionText1 != null)
{
surveyViewModel.QuestionText1 = currentSurveyViewModel.QuestionText1;
}
if (currentSurveyViewModel.QuestionText2 != null)
{
surveyViewModel.QuestionText2 = currentSurveyViewModel.QuestionText2;
}
if (currentSurveyViewModel.QuestionText3 != null)
{
surveyViewModel.QuestionText3 = currentSurveyViewModel.QuestionText3;
}
if (currentSurveyViewModel.QuestionText4 != null)
{
surveyViewModel.QuestionText4 = currentSurveyViewModel.QuestionText4;
}
if (currentSurveyViewModel.QuestionText5 != null)
{
surveyViewModel.QuestionText5 = currentSurveyViewModel.QuestionText5;
}
if (currentSurveyViewModel.QuestionText6 != null)
{
surveyViewModel.QuestionText6 = currentSurveyViewModel.QuestionText6;
}
if (currentSurveyViewModel.QuestionText7 != null)
{
surveyViewModel.QuestionText7 = currentSurveyViewModel.QuestionText7;
}
}
if (direction == "Countinue to submit this survey")
return View("something", surveyViewModel);
else if (direction == "Add a New Question to this survey")
{
TempData["SurveyView"] = surveyViewModel;
return View("QuestionTwo", surveyViewModel);
}
else if (direction == "Previous Step")
{
TempData["SurveyView"] = surveyViewModel;
return View("Index", surveyViewModel);
}
else return View();
}
Instead of fighting the MVC framework in this way, here are a couple of other ways you could do it that might make more sense.
1)consider saving answer as you go to the database.
The record could be some kind of temporary record that isn't considered "real" until the end of the questionaire when the user does a final submit.
2) If the question data is not too big, render each question in it's own section (a div, a tab control) in the one view, and deal with switching between sections in javascript on button clicks. You could use your existing ViewModel to carry all questions into the view, and have them all posted and saved at the end. Make it a list of questions instead of 8 properties that are question, and you could even have a for loop in your view that renders a partial for each question. The partial could deal with next and previous buttons etc.
To pass the complete model from one page to the next, you have to ensure that all the properties of the model are part of the form and get posted back with each form submit operation back to the server.
To accomplish this, in your view you need to create hidden form fields, using #HTML.HiddenFor that contain all the data of the model even if you are not showing it to the user on a particular page.
Every time you make a synchronous HTTP request you are, in fact, reloading the same page, just with a different returned value. If you want the data to persist, you would benefit from learning more about asynchronous requests (AJAX) that can send/receive information without redirection...otherwise you need to persist the answer to question 1 and return it along with the view for question 2...then for question 3 you would need to ensure question 1 and 2 are persisted and return their values along with the context for question 3.
You 'could' go about this with hidden fields as mentioned, but you should really consider this is as a chance to learn something new and useful. Utilizing hidden fields is behind the times and really really obsolete.
Option 1: TempData
This same issue is addressed here: Can we pass model as a parameter in RedirectToAction?
The problem is your use of RedirectToAction. You cannot pass a model that way, only primitive types. You need to utilize TempData for this process:
[HttpPost]
public ActionResult QuestionOneNext(SurveyViewModelNew surveyViewModel, string direction)
{
var currentSurveyViewModel = surveyViewModel ?? (SurveyViewModel)TempData["SurveyView"];
if (direction == "Countinue to submit this survey")
{
TempData["SurveyView"] = currentSurveyViewModel;
return RedirectToAction("Edit", "something", null);
}
if (direction == "Add a New Question to this survey")
{
return View("QuestionTwo", currentSurveyViewModel);
//return RedirectToAction("QuestionTwo", "CreateSurveyStep2", surveyViewModel);
}
if (direction == "Previous Step")
{
TempData["SurveyView"] = currentSurveyViewModel;
return RedirectToAction("Index", "CreateSurveyStep1", null);
}
return View();
}
[HttpPost]
public ActionResult QuestionTwo(SurveyViewModelNew surveyViewModel, string direction)
{
var currentSurveyViewModel = surveyViewModel ?? (SurveyViewModel)TempData["SurveyView"];
if (direction == "Countinue to submit this survey")
{
TempData["SurveyView"] = currentSurveyViewModel ;
return RedirectToAction("Edit", "NutStorage", null);
}
if (direction == "Add a New Question to this survey")
{
//return RedirectToAction("QuestionThree", "CreateSurveyStep2", surveyViewModel);
return View("QuestionThree", "CreateSurveyStep2", currentSurveyViewModel );
}
if (direction == "Previous Step")
{
TempData["SurveyView"] = currentSurveyViewModel ;
return RedirectToAction("QuestionOne", "CreateSurveyStep2", null);
}
return View();
}
Option 2: RouteValueDictionary
There is another option for utilizing complex types and that is using the RouteValueDictionary. This is covered in this very similar question: Passing object in RedirectToAction
The general idea, for your RedirectToAction calls would be to do this:
return RedirectToAction("Edit", "NutStorage", new RouteValueDictionary(surveyViewModel));

Categories