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>
Related
I want to use data annotations in my app and the problem is when I click in submit button and don't fill the required field I don't see any error message and it submits. In the controller, the model.state works fine, but I think I should see the error message.
The model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace ValidationTest.Models
{
public class User
{
[Required(ErrorMessage = "Enter your name.")]
public string Name { get; set; }
public string Lastname { get; set; }
}
}
The View:
#model ValidationTest.Models.User
#{
ViewBag.Title = "Index";
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
#using (Html.BeginForm("Record", "Home"))
{
#Html.Label("Name:")
#Html.TextBoxFor(m => m.Name)
#Html.ValidationMessageFor(m => m.Name)
<br />
#Html.Label("Lastname:")
#Html.TextBoxFor(m => m.Lastname)
#Html.ValidationMessageFor(m => m.Lastname)
<input type="submit" value="Record" />
}
</body>
</html>
The controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ValidationTest.Models;
namespace ValidationTest.Controllers
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Record(User usr)
{
if (ModelState.IsValid)
{
return Content("It Worked!");
}
return RedirectToAction("Index");
}
}
}
In Scripts folder inside the ASP.NET MVC project i have:
bootstrap.js
bootstrap.min.js
jquery-3.2.1.intellisense.js
jquery-3.2.1.js
jquery-3.2.1.min.js
jquery-3.2.1.min.map
jquery-3.2.1.slim.js
jquery-3.2.1.slim.min.js
jquery-3.2.1.slim.min.js
modernizr-2.6.2.js
You will have to add JavaScript script references of jquery.validate.min.js and jquery.validate.unobtrusive.min.js for client side validation to work.
Move return RedirectToAction("Index"); inside if (ModelState.IsValid) condition.
return view(); should be added outside if condition.
so on my get Edit controller i have the following:
public ActionResult Edit(string id)
{
using (ISession session = NhibernateHelper.OpenSession())
{
var site= session.Get<Sitios>(id);
return View(site);
}
}
Which works for bringing my normal textfield properties from that specific site, BUT where im having the problem where im stuck at is when i want to bring in dropdown list in it as well, on the Create action i solved that by using this code:
//GET: Sitios/Create
public ActionResult Create()
{
using (ISession session = NhibernateHelper.OpenSession())
{
var deptos = session.Query<Departaments>().ToList();
var SiteCopy =new Sitios
{
Departaments = deptos
};
return View(SiteCopy);
}
The model part of that specific list is:
public class Sitios
{
//more code
public virtual List<Departamentos> Departamentos { get; set; }
}
And the view for Create action i used which is what i would like to be able to use on my edit view as well is
<div class="form-group">
<label class="control-label col-md-2"> Departament </label>
<div class="col-md-10">
#Html.DropDownListFor(model => model.id_departamento, new SelectList(Model.Departamentos, "id_departamento", "description")
</div>
</div>
So in summary i would like to see if its possible to use the below code which works fine for bringing the string properties of that specific site PLUS add the dropdown in it as well.
public ActionResult Edit(string id)
{
using (ISession session = NhibernateHelper.OpenSession())
{
var sitio = session.Get<Sitios>(id);
return View(site);
}
}
Thanks!
I don't understand why ModelState.isValid give me in all the ways. I set something in the email returns true and I pùt empty field, it returns true too. My question ism, what do I have to do to return true when the field is empty and nothing whn I wrote the email?
I have the next view file:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<div style="padding-top:5px;clear:both;"></div>
<% using (Html.BeginForm()) { %>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Email usuario</legend>
<div class="editor-field">
<%: Html.TextBoxFor(m => m.Email) %>
<%: Html.ValidationMessageFor(m => m.Email) %>
</div>
<input type="submit" value="Enviar Email" />
</fieldset>
<% } %>
<div style="padding-top:5px;clear:both;"></div>
</asp:Content>
The Controller is:
//
// GET: /Account/EmailRequest
public ActionResult EmailRequest()
{
return View();
}
[HttpPost]
public ActionResult EmailRequest(string email)
{
if (ModelState.IsValid)
{
// save to db, for instance
return RedirectToAction("AnotherAction");
}
return View();
}
My model class is:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Web.Mvc;
using System.Web.Security;
namespace PortalClient.Models
{
public class EmailRequest
{
[Required(ErrorMessage = "required")]
public string Email { get; set; }
}
}
Change the signature of your post action from string email to EmailRequest model and then check the state. e.g.
[HttpPost]
public ActionResult EmailRequest(EmailRequest model)
{
if (ModelState.IsValid)
{
// save to db, for instance
return RedirectToAction("AnotherAction");
}
return View();
}
You need to bind a view model to your view.
Change your EmailRequest model to something more descriptive like:
public class EmailRequestViewModel
{
[Required(ErrorMessage = "Required")]
public string Email { get; set; }
}
Your get action method would look something like:
public ActionResult EmailRequest()
{
EmailRequestViewModel viewModel = new EmailRequestViewModel();
return View(viewModel);
}
Your post action method:
public ActionResult EmailRequest(EmailRequestViewModel viewModel)
{
// Check for null view model
if (!ModelState.IsValid)
{
return View(viewModel);
}
// Do whatever you need to do
return RedirectToAction("List");
}
And then your view. Please excuse the ASP.NET MVC 4 code, MVC 2 is prehistoric :) This is just part of your view:
#model YourProject.ViewModels.EmailRequestViewModel
#using (Html.BeginForm())
{
#Html.TextBoxFor(x => x.Email)
#Html.ValidationMessageFor(x => x.Email)
}
I hope this helps.
you need to bind your model with binder first to have ability to chek it by Modelstat.IsValid
public ActionResult EmailRequest()
{
EmailRequest email = new EmailRequest();
TryUpdateModel(email);
if (ModelState.IsValid)
{
// save to db, for instance
return RedirectToAction("AnotherAction");
}
return View();
}
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.
I've got an MVC 3 form in a strongly typed view where one of the fields I need submitted is inside of a jQuery dialog. I have not been able to get this field to be part of the POST parameters submitted. Why oh why?
The View:
#model My.Models.DialogFieldModel
#{
ViewBag.Title = "Index";
}
<script type="text/javascript">
$(document).ready(function () {
$('#aDialog').dialog({
autoOpen: true,
height: 250, width: 400,
modal: true,
buttons: {
"Ok!": function () {
$(this).dialog("close");
}
}
});
});
</script>
<h2>Index</h2>
#using (Html.BeginForm("PostDialogField", "DialogField"))
{
#Html.ValidationSummary(true)
<fieldset>
#Html.HiddenFor(m => m.ID)
#Html.DisplayFor(m => m.message)
<div id="aDialog">
<h3>Fill in this message!</h3>
<div class="editor-field">
#Html.EditorFor(m => m.message)
</div>
</div>
<p><input type="submit" value="Submit Message" /></p>
</fieldset>
}
The Model:
using System;
namespace My.Models
{
public class DialogFieldModel
{
public int ID { get; set; }
public String message { get; set; }
public DialogFieldModel()
{
message = "Default";
}
}
}
The controller:
using System;
using System.Web;
using System.Web.Mvc;
using WellTrkd.Models;
namespace My.Controllers
{
public class DialogFieldController : Controller
{
public ActionResult Index()
{
DialogFieldModel dfm = new DialogFieldModel(); // set default message
return View(dfm);
}
[HttpPost]
public ActionResult PostDialogField(DialogFieldModel dfm)
{
String message = dfm.message;
if (message != "Default")
//Yay!
return RedirectToAction("Index");
else // Boo
return RedirectToAction("Index");
}
}
}
Unfortunately the #message field is never submitted along with the rest of the HTML POST parameters (checked in network tab of chrome dev view) unless I take it out of the dialog. The result is that in the PostDialogField action dfm.message contains the "Default" string, even if I've changed the message in the dialog.
I know I could add a hidden field to the form that is kept synchronized with the field in the dialog, but I feel I'm missing something. Any thoughts oh wise ones?
Your problem is that the element you turn into a dialog is moved out of the form towards a new dialog-element at the bottom of the DOM. And since it's not part of the form any more, it won't be submitted when the form is submitted.
If you'd destroy the dialog when closing it, it would be moved back to where it was, but I can't see if that's what is desired. The other option is to sync elements.