ASP.net MVC 3 Edit/Delete issue - c#

So I just finished working the project at http://msdn.microsoft.com/en-us/data/gg685489. I am trying to create a CRUD for use with an external database that already exists and I am just using the project as a guide for my own work. I have been able to change certain variable names and connections to connect with the database that I am trying to work with and I have even displayed the data I want using the index method. I have also been able to get the create method working and I am able to create new data in the DB I am working with. Unfortunatlty I have not been able to pull data in when using the Edit or Delete methods or save/delete after I have made the changes I want.
For example when I press the edit button it should pull the record that I clicked on so that I could edit a particular records information but instead it threw an error saying that this variable cannot accept a null value which is why I changed the int to a string in the edit delete methods. This part is solved
I think the issue has something to do with the Edit and Delete methods not pulling the recordset when I tell it to. Does anyone have any idea why it's not pulling the record sets when I edit/delete or saving my changes after I tell it to save?
I have posted my PaController class which has my CRUD methods in it for diagnosis as well as my iamp_mapping class file which has the 3 fields I need to work with. I am 90% sure I am doing something wrong with the controller, but if you need anymore code/information about the issue please leave me a note I will be checking back A LOT because I am soo stuck! Thanks so much for your help!
PaController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DBFirstMVC.Models;
using System.Data;
namespace DBFirstMVC.Controllers
{
public class PaController : Controller
{
PaEntities db = new PaEntities();
//
// GET: /Pa/
public ActionResult Index()
{
using (var db = new PaEntities())
{
return View(db.iamp_mapping.ToList());
}
}
//
// GET: /Pa/Details/5
public ActionResult Details(int id)
{
return View();
}
//
// GET: /Pa/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Pa/Create
[HttpPost]
public ActionResult Create(iamp_mapping IAMP)
{
try
{
using (var db = new PaEntities())
{
db.iamp_mapping.Add(IAMP);
db.SaveChanges();
}
return RedirectToAction("Index");
}
catch
{
return View();
}
}
//
// GET: /Pa/Edit/5
public ActionResult Edit(string id)
{
using (var db = new PaEntities())
{
return View(db.iamp_mapping.Find(id));
}
}
//
// POST: /Pa/Edit/5
[HttpPost]
public ActionResult Edit(string id, iamp_mapping IAMP)
{
try
{
using (var db = new PaEntities())
{
db.Entry(IAMP).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
}
catch
{
return View();
}
}
//
// GET: /Pa/Delete/5
public ActionResult Delete(string id)
{
using (var db = new PaEntities())
{
return View(db.iamp_mapping.Find(id));
}
}
//
// POST: /Pa/Delete/5
[HttpPost]
public ActionResult Delete(string id, iamp_mapping IAMP)
{
try
{
using (var db = new PaEntities())
{
db.Entry(IAMP).State = EntityState.Deleted;
db.SaveChanges();
return RedirectToAction("Index");
}
}
catch
{
return View();
}
}
}
}
iamp_mapping
using System;
using System.Collections.Generic;
namespace DBFirstMVC.Models
{
public partial class iamp_mapping
{
public string PA { get; set; }
public string MAJOR_PROGRAM { get; set; }
public string INVESTMENT_AREA { get; set; }
}
}
Edit View Code
#model DBFirstMVC.Models.iamp_mapping
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>iamp_mapping</legend>
<div class="editor-label">
#Html.LabelFor(model => model.PA)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PA)
#Html.ValidationMessageFor(model => model.PA)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.MAJOR_PROGRAM)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.MAJOR_PROGRAM)
#Html.ValidationMessageFor(model => model.MAJOR_PROGRAM)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.INVESTMENT_AREA)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.INVESTMENT_AREA)
#Html.ValidationMessageFor(model => model.INVESTMENT_AREA)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Index.cshtml
#model IEnumerable<DBFirstMVC.Models.iamp_mapping>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
PA
</th>
<th>
MAJOR PROGRAM
</th>
<th>
INVESTMENT AREA
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.PA)
</td>
<td>
#Html.DisplayFor(modelItem => item.MAJOR_PROGRAM)
</td>
<td>
#Html.DisplayFor(modelItem => item.INVESTMENT_AREA)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.PA }) |
#Html.ActionLink("Details", "Details", new { id=item.PA }) |
#Html.ActionLink("Delete", "Delete", new { id=item.PA })
</td>
</tr>
}
The ActionLink is what I had to fix, when I first posted the question it looked like this
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ })
I changed it to the actual primary key PA and deleted the comments. This fixed the problem of data not filling in when trying to edit a row!
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.PA }) |
#Html.ActionLink("Details", "Details", new { id=item.PA }) |
#Html.ActionLink("Delete", "Delete", new { id=item.PA })
</td>
</tr>
}
Delete.cshtml
#model DBFirstMVC.Models.iamp_mapping
#{
ViewBag.Title = "Delete";
}
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<fieldset>
<legend>iamp_mapping</legend>
<div class="display-label">PA</div>
<div class="display-field">
#Html.DisplayFor(model => model.PA)
</div>
<div class="display-label">MAJOR_PROGRAM</div>
<div class="display-field">
#Html.DisplayFor(model => model.MAJOR_PROGRAM)
</div>
<div class="display-label">INVESTMENT_AREA</div>
<div class="display-field">
#Html.DisplayFor(model => model.INVESTMENT_AREA)
</div>
</fieldset>
#using (Html.BeginForm()) {
<p>
<input type="submit" value="Delete" /> |
#Html.ActionLink("Back to List", "Index")
</p>
}
Global.asax.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace DBFirstMVC
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Pa", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
}

Your problem here appears that when you click on the edit button/link the Edit action will expect an id of type int (if you use int), however this can be switched as optional if you use int?...which is how the MVC behaves...your best bet here is to try using a url say something like http://urwebsite.com/Pa/Edit?id=[use a valid id]...with this you will have a id in your Edit action...
Update
I think the issue you are having here is that the Id value in the Edit action method is null...and the MVC engine is unable to recognize an id value from your Url pattern
So, the page where you have the edit link/button you can use something like
Edit
If you have a for loop where you are displaying a collection of records...
#foreach(var item in Model)
{
Edit
}
Also make sure that you have a routing configured for url pattern /Pa/Edit/{id}
You may wanna read this Article if you want to know more about routing in mvc.
This will ensure that when a Get request is made to the edit action method, the id value will be recognized
Hope this helps...

My link wouldnt pick the id up for some reason, so I found a solution from one course.
He added the fifth argument "null" to the function like this
<td>#Html.ActionLink("Edit", "Edit", "Account", new {id = account.Id }, null)</td>
(text, action, controller, route value, null or HTML atribute)
this fixed it for me.

Related

Showing multiple tables with partial views. Asp.Net Mvc

I want to use 3 partial views to display my search result(Client name) in 3 different tables. I do not want to show any info from the tables before the search has been completed. As i have understood you can only use one model per view, unless you make some workarounds.
I have tried to make a view model so i can reference the multiple tables from both the index and the partial views. But can't figure it out. Since the methods for the 3 different tables will be the pretty much same i am only going to post the code for the client table. Any help or pointers would be much appreciated
ViewModel:
public class ViewModel
{
public List<Clients> allClients { get; set; }
public List<OrderLines> allOrders { get; set; }
public List<ViewNewOrderSum> allViewNewOrderSum { get; set; }
}
HomeController:
using testForAutofill.Models;
public class HomeController : Controller
{
test_Db_Context db = new test_Db_Context();
// GET: Home
public ActionResult Index()
{
ViewModel vm = new ViewModel();
vm.allClients = GetClients();
return View();
}
private List<Clients> GetClients()
{
List<Clients> clientList = new List<Clients>();
clientList = db.Clients.ToList();
return clientList;
}
[HttpPost]
public ActionResult Index(string searchTerm)
{
Scaleit_Db_Context db = new Scaleit_Db_Context();
List<Clients> orderSums;
if (string.IsNullOrEmpty(searchTerm))//Fix this!
{
orderSums = db.Clients.ToList();
}
else
{
orderSums = db.Clients.Where(x => x.Name.Equals(searchTerm)).ToList();
}
return View(orderSums);
}
IndexView:
#using testForAutofill.Models;
#model testForAutofill.Models.ViewModel
#if (Model.allClients != null && Model.allClients.Count() > 0)
{
#using (Html.BeginForm())
{
<b>Kundenavn:</b>
#Html.TextBox("searchTerm", null, new { id = "txtSearch" })
<input type="submit" value="🔍 Search" class="btn btn-primary" id="btn-search" />
#using (Html.BeginForm())
{
<div class="card-container">
<div class="card border-primary mb-3 card-client" style="max-width: 40rem;">
<div class="card-header">Kunde</div>
<div class="card-body">
<table class="table table-hover">
#foreach (Clients clients in Model.allClients)
{
#Html.Partial("_Client", clients)
}
</table>
</div>
</div>
</div>
}
_Client:
#model testForAutofill.Models.ViewModel
//Tried both DisplayFor and not.
<tr>
<th>Kunde:</th>
<td>#Html.Model.allClients.Name</td>// This is where the error gets
// thrown.
</tr>
<tr>
<th>Org.nr:</th>
<td>#Html.DisplayFor(modelItem => clients.OrgNr)</td>
</tr>
<tr>
<th>Adresse:</th>
<td>#Html.DisplayFor(modelItem => clients.Address1)</td>
#if (clients.Address2 != null)
{
<td>#Html.DisplayFor(modelItem => clients.PostNr)</td>
}
</tr>
The program/webpage doesnt run, and i get the error message:
" CS1061: 'HtmlHelper' does not contain a definition for
'Model' and no extension method 'Model' accepting a first argument of
type 'HtmlHelper' could be found (are you missing a using
directive or an assembly reference?)".
At the commented line in the Partial view.
TRY:
Set object on viewData
inside controller:
ActionResult SomeView(){
ViewData["object"] = theObj;
return View();
}
inside cshtml:
#using objectNamespace
#(((objectType)ViewData["object"]).name)

How to refresh a page in MVC

I found out that my page actually reload/refresh, but require additional reload to see the content I just added. However I've to reload again to see the data, OR add another data to see the previous data..
I added my controller code below:
(CreateComment and Comment(display comments) are inside Details(details about book) View )
CreateComment:
public ActionResult CreateComment(Guid id) {
return View(new CommentToBook { BookId = id });
}
[HttpPost]
public ActionResult CreateComment(CommentToBookVm model) {
if (ModelState.IsValid) {
var m = new CommentToBook { Comment = model.Comment, BookId = model.BookId };
m.UserId = new Guid(Session["UserID"].ToString());
m.CreatedDate = DateTime.Now;
db.CommentToBooks.Add(m);
db.SaveChanges();
}
return View(model);
}
View for createComment
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.HiddenFor(s => s.BookId)
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Comment, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Comment, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Comment, "", 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>
Details (have Comment and CreateComment inside)
public ActionResult Details(Guid? id) {
Book book = db.Books.Find(id);
return View(book);
}
View
<h2>Details</h2>
#Html.Action("Rating", new { id = Model.Id })
<div>
<h4>Books</h4>
<hr/>
<dl class="dl-horizontal">
<dt>
#Html.DisplayNameFor(model => model.Title)
</dt>
<dd>
#Html.DisplayFor(model => model.Title)
</dd>
#*and so on...*#
</dl>
</div>
#Html.Action("Comment", new { id = Model.Id })
#Html.Action("CreateComment", new { id = Model.Id })
And the Comment to list all comments.
public ActionResult Comment(Guid? id) {
var comment = db.CommentToBooks.Where(c => c.BookId == id);
return View(comment.ToList());
}
view:
<table class="table">
<tr>
<th>
User
</th>
<th>
#Html.DisplayNameFor(model => model.Comment)
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.ActionLink(item.User.UserName, "VisitUser", new { id = item.UserId })
</td>
<td>
#Html.DisplayFor(modelItem => item.Comment)
</td>
</tr>
}
</table>
I think it's about what I am returning in controller, I tried some different alternative but I just end up hitting the error:
Description:
An unhandled exception occurred during the execution of the current
web request. Please review the stack trace for more information about
the error and where it originated in the code.
Exception Details: System.NullReferenceException: Object reference not
set to an instance of an object.
Source Error:
Line 9: #Html.Action("Comment", new { id = Model.Id })
OR
child actions are not allowed to perform redirect actions.
If I try to RedirectToAction for CreateComment etc.
I would appreciate an example of code as I find it hard to understand new concepts by just words.
Your code is returning the view for CreateComment method. Looks like you marked this action method as ChildActions only. You should not be using ChildAction for a use case like this. ChildActions should be used for rendering something to the view. Ex : A Menu bar in your app.
Even if you remove the [ChildAction] from the CreateComment action method, when you return the model back to the form, it is going to render the markup generated by the CreateComment view. That means you will loose the list of comments (which was loaded when you called the Details view).
Ideally, for all data insertion usecases, you should follow P-R-G pattern.
PRG stands for POST - REDIRECT- GET. That means, you submit a form and after successfully saving data to db, you do return a redirect result to the client and client(browser) will issue a totally new http request for the GET action method in which you wiil query the db table and return the results.
But since your form is loaded to the main view through a call to the Html.Action method, you won't get the desired results (list of comments and the validation messages in same view). One thing to make it to work is, by enabling unobtrusive client side validation. In that case, the form won't be actually submitted to the server. Instead client side validation will be invoked and validation messages will be shown to the user in the same page(no page reload!).
You can enable it by adding reference to these 2 scripts in your view(or layout)
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
Redirect to the GET action to show all comments after successful save of the posted comment.
[HttpPost]
public ActionResult CreateComment(CommentToBookVm model)
{
if (ModelState.IsValid)
{
//your existing code to save data to the table
return RedirectToAction("Details","Book", new { id=model.BookId} );
}
// Hoping that the below code might not execute as client side validation
// must have prevented the form submission if there was a validation error.
return View(model);
}
Another option which does not rely on just client side validation is to create a flat view model which has the list of existing comments and properties for the new comment form. When you submit the form, if validation fails, reload the Comments property again and return the view model back to the form.
public class ListAndCreateVm
{
[Required]
public string NewComment { set;get;}
public Guid BookId { set;get;}
public List<CommentVm> Comments { set;get;}
}
public class CommentVm
{
public string Comment { set;get;}
public string Author { set;get;}
}
and in your Details action, load Comments and send this to the view
public ActionResult Details(Guid id)
{
var vm = new ListAndCreateVm { BookId= id};
vm.Comments = GetComments(id);
return View(vm);
}
private List<CommentVm> GetComments(Guid bookId)
{
return db.CommentToBooks.Where(c => c.BookId == bookId)
.Select(x=> new CommentVm { Comment = x.Comment})
.ToList();
}
and in your view
#model ListAndCreateVm
#foreach(var c in Model.Comments)
{
<p>#c.Comment</p>
}
<h4>Create new comment</h4>
#using(Html.BeginForm())
{
#Html.ValidationSummary(false, "", new {#class = "text-danger"})
#Html.TextBoxFor(s=>s.NewComment)
#Html.HiddenFor(f=>f.BookId)
<input type="submit" />
}
Now along with using PRG pattern, make sure to reload Comments property of the view model when Model validation fails
[HttpPost]
public ActionResult Details(ListAndCreateVm model)
{
if(ModelState.IsValid)
{
// to do : Save
return RedirectToAction("Details,"Book",new { id=model.BookId});
}
//lets reload comments because Http is stateless :)
model.Comments = GetComments(model.BookId);
return View(model);
}

.NET MVC C# Error - A data source must be bound before this operation can be performed

I am encountering the following error:
A data source must be bound before this operation can be performed.
I have a text box, the user enters a name, and clicks the submit button. The name is added to a list. I have researched the error but everything I try gives me the same error. Any insight on what I am doing wrong will be appreciated.
Model:
namespace RangeTest.Models
{
public class UserNameModel
{
[Key]
public int Id { get; set; }
[Display(Name = "Names Added List")]
public string FullName { get; set; }
}
}
Controller:
public ActionResult Admin()
{
return View();
}
[HttpPost]
public ActionResult Admin(UserNameModel model, IEnumerable<RangeTest.Models.UserNameModel> t)
{
List<UserNameModel> userList = new List<UserNameModel>();
model.FullName = t.FirstOrDefault().FullName;
userList.Add(model);
return View(userList.ToList());
}
View (Admin.cshtml):
#model IEnumerable<RangeTest.Models.UserNameModel>
#{
ViewBag.Title = "";
}
<div class="container"></div>
<div class="jumbotron">
#using (Html.BeginForm("Admin", "UserNames", FormMethod.Post, new { #id = "WebGridForm" }))
{
#Html.ValidationSummary(true)
WebGrid dataGrid = new WebGrid(Model, canPage: false, canSort: false);
//Func<bool, MvcHtmlString> func =
//(b) => b ? MvcHtmlString.Create("checked=\"checked\"") : MvcHtmlString.Empty;
<div class="table-bordered">
<div class="Title">Admin - Add names to range list</div><br />
<table id="TblAdd"class="table">
<tr>
#{
RangeTest.Models.UserNameModel t = new RangeTest.Models.UserNameModel();
}
#Html.Partial("_AddDynTable", t)
</table>
</div>
<div class="table-responsive">
<div class="Title">Names Added to Range List</div>
<table class="table">
<tr>
<td >
#dataGrid.GetHtml(columns: dataGrid.Columns(dataGrid.Column(format: #<text>#item</text>),
dataGrid.Column("", format: (item) => Html.ActionLink("Delete", "Delete", new { id = item.id }))))
</td>
</tr>
</table>
</div>
}
</div>
Partial View (_addDynTable.cshtml)
#model RangeTest.Models.UserNameModel
<tr>
<td>
Enter Full Name: #Html.TextBoxFor(m => m.FullName)
#*<input type="button" value="Create" id="ClickToAdd" />*#<input class="CreateBtn" type="submit" value="Add to List" /></td>
</tr>
Can you link info about the error please?
One thing I can see is your t object is null when you pass it to the partial view
RangeTest.Models.UserNameModel t = new RangeTest.Models.UserNameModel();
A new UserNameModel with no data in it, if your error is there that might be the problem

Adding user to roles using check boxes in MVC 4 ASP.NET

I am new to the MVC framework as well as ASP.NET so I apologize for any sloppy code.
I am creating an application that requires an Admin to set the roles of new users that register. When the Admin logs into the application, they are automatically directed to an Admin page that displays a list of users that have registered with the app. The admin has the ability to choose the role for the new user.
Here is my controller for the admin:
public class AdminTestController : Controller
{
private UsersContext db = new UsersContext();
// GET: /AdminTest/
[Authorize(Roles = "Admin")]
public ActionResult Index()
{
var model = db.UserProfiles.ToList();
return View(model);
}
[HttpPost]
public ActionResult Submit(string userName, string selectedRole)
{
Roles.AddUserToRole(userName,selectedRole);
return View("Index");
}
Here is the corresponding view:
#model IEnumerable<WAP.Models.UserProfile>
#{
ViewBag.Title = "Index";
}
...
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.UserId)
</td>
<td>
</td>
<td>
#Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.UserId }) |
#Html.ActionLink("Details", "Details", new { id=item.UserId }) |
#Html.ActionLink("Delete", "Delete", new { id=item.UserId })
#using (Html.BeginForm("Submit", "AdminTest", FormMethod.Post))
{
<select name ="selectedRole">
<option value="Null"></option>
<option value="Manager">Manager</option>
<option value="Agent">Agent</option>
</select>
<input id="SubmitChange" type="submit" value="Submit" />
<input id="userName" type ="text" value= "#item.UserName" name= "userName" hidden ="hidden" />
}
</td>
</tr>
}
Thank you in advance for taking the time to look at this question and any help that you can provide.
You can use Html.DropDownList helper for this. Firstly you will need to prepare your roles collection in controller to populate it. Here is the sample code:
[Authorize(Roles = "Admin")]
public ActionResult Index()
{
var model = db.UserProfiles.ToList();
var rolesCollection = new List<string> {"Null", "Manager", "Agent"};
ViewBag.Roles = new SelectList(rolesCollection);
return View(model);
}
Then in your view:
#using (Html.BeginForm("Submit", "AdminTest", FormMethod.Post))
{
#Html.Hidden("userName", item.UserName)
#Html.DropDownList("selectedRole", (SelectList)ViewBag.Roles)
<input id="SubmitChange" type="submit" value="Submit" />
}
You can also use Html.RadioButton helper in such way:
#using (Html.BeginForm("Submit", "AdminTest", FormMethod.Post))
{
#Html.Hidden("userName", item.UserName)
#Html.RadioButton("selectedRole", "Null", true)
#Html.RadioButton("selectedRole", "Manager")
#Html.RadioButton("selectedRole", "Agent")
<input id="SubmitChange" type="submit" value="Submit" />
}
If you want to make multiple roles selected at the same time, I suggest using some jQuery plugin, such as jQuery.chosen and Html.ListBox helper.
Use EditorTemplates for all enums (Create "Role" enum):
#model Enum
#Html.DropDownListFor(m => Enum.GetValues(Model.GetType()).Cast<Enum>().Select(m =>
new SelecteListItem {Selected = "your logic", Text = "", Value = ""}))
Or use custom partial view by current enum.

C# pre-populating textarea from database

I have a small website with a Homepage which displays x2 paragraphs of text. These paragraphs are populated from a single record in a database containing 3 fields ("ID", "para1" and "para2"). This record is updated via a form which contains x2 textareas (assigned to update "para1" and "para2"), allowing me to type into the textarea, click "update" and then the two paragraphs on the Homepage will update to reflect the new text.
To navigate to the form page that contains the textareas from the homepage I click an "admin" link which takes me to a logon page, I enter username and password and click "login" and this forwards me on to the "update" page.
What I'd like, is the x2 textarea inputs to be pre-populated with the data stored in the "para1" and "para2" fields in the database table. This way, if someone wanted to make a minor edit to either of the paragraphs on the homepage then they won't need to re-type the whole thing from scratch.
I'm using C# Razor in Microsoft Visual Web Developer Express. I am a total beginner at not just this, but any form of development work, so I'm learning as I'm going, please be gentle :-)
Code examples below:
(the View page):
#model DFAccountancy.Models.Data
#{
ViewBag.Title = "Update";
}
<h2>Update</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"> </script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Data</legend>
<div class="editor-label">
#Html.LabelFor(model => model.para1)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.para1, new { cols = 75, #rows = 5 })
#*#Html.EditorFor(model => model.para1)*#
#Html.ValidationMessageFor(model => model.para1)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.para2)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.para2, new { cols = 75, #rows = 5 })
#*#Html.EditorFor(model => model.para2)*#
#Html.ValidationMessageFor(model => model.para2)
</div>
<p>
<input type="submit" value="Update" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
(the Model):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;
namespace DFAccountancy.Models
{
public class Data
{
[DataType(DataType.MultilineText)]
public int ID { get; set; }
public string para1 { get; set; }
public string para2 { get; set; }
}
public class DataDBContext : DbContext
{
public DbSet<Data> Data { get; set; }
}
}
(the Controller):
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DFAccountancy.Models;
namespace DFAccountancy.Controllers
{
public class DataController : Controller
{
private DataDBContext db = new DataDBContext();
//
// GET: /Data/
public ViewResult Index()
{
return View(db.Data.ToList());
}
//
// GET: /Data/Details/5
public ViewResult Details(string id)
{
Data data = db.Data.Find(id);
return View(data);
}
//
// GET: /Data/Update/5
public ActionResult Update()
{
return View();
}
//
// POST: /Data/Update/5
[HttpPost]
public ActionResult Update(Data data)
{
if (ModelState.IsValid)
{
data.ID = 1; //EF need to know which row to update in the database.
db.Entry(data).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index", "Home");
}
return View(data);
}
}
}
You just need to update your Update method to include passing in an Id
//
// GET: /Data/Update/5
public ActionResult Update()
{
Data data = db.Data.Find("1");
return View(data);
}
In addition the link to the update method will need to be updated to pass that Id in as well. Assuming you're using the standard list template for MVC.
<td>
#Html.ActionLink("Update", "Update") |
...
</td>

Categories

Resources