ViewModel is null upon form submit - c#

What i am trying to do is create a SubCategory object. In order to do so i have made a viewmodel that will supply my view with the nescesarry data (including a category object that the subcategory will be bound to.)
when i post my form the viewmodel is returned to my controller but all the properties of my subcategory and my selected value from a dropdownlist is null.
what am i doing wrong? :S
view:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.master" Inherits="System.Web.Mvc.ViewPage<SkyLearn.Areas.Categories.Models.CategoryViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Create
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Create</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>
<form action="" method="post" enctype="multipart/form-data">
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>SubCategory</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.subcategory.Title) %>
</div>
<div class="editor-field">
<%: Html.EditorFor(model => model.subcategory.Title)%>
<%: Html.ValidationMessageFor(model => model.subcategory.Title)%>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.subcategory.Icon)%>
</div>
<div class="editor-field">
<input type="file" name="icon" id="icon"/>
</div>
<%: Html.DropDownListFor(selectedcategory => Model.selectedCategory, Model.categories) %>
<div class="editor-label">
<%: Html.LabelFor(model => model.subcategory.Description)%>
</div>
<div class="editor-field">
<%: Html.EditorFor(model => model.subcategory.Description)%>
<%: Html.ValidationMessageFor(model => model.subcategory.Description)%>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
</form>
<div>
<%: Html.ActionLink("Back to List", "Index") %>
</div>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="SideContent" runat="server">
</asp:Content>
Controller:
[Authorize(Roles = "administrator")]
[HttpPost]
public ActionResult Create(CategoryViewModel viewmodel, HttpPostedFileBase Icon)
{
SubCategory subcategory = viewmodel.subcategory;
subcategory.Category = categorycontroller.getCategoryByName(viewmodel.selectedCategory);
if (Icon != null && Icon.ContentLength > 0)
{
// extract only the filename
var fileName = Path.GetFileName(Icon.FileName);
// store the file inside ~/App_Data/uploads folder
var path = Path.Combine(Server.MapPath("../../Content/icons/"), fileName);
Icon.SaveAs(path);
subcategory.Icon = fileName;
}
if (ModelState.IsValid)
{
db.subcategories.Add(subcategory);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(subcategory);
}
ViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.Web.Mvc;
namespace SkyLearn.Areas.Categories.Models
{
public class CategoryViewModel
{
public List<SelectListItem> categories;
public SubCategory subcategory;
public string selectedCategory;
public CategoryViewModel()
{
categories = new List<SelectListItem>();
subcategory = new SubCategory();
selectedCategory = "";
}
}
}
the viewmodel contains a list of categories that the subcategory im trying to create can be bound to. it also contains a subcategory object i can use to create the subcategory from. and the last property is a string i want to use for binding the choice in the dropdownlist.

ASP.Net MVC3's SelectListItem doesn't behave how you'd expect. Also, try Html.DropDownListFor() rather than Html.EditorFor() to make your dropdown list.
In the ViewModel:
public IList<string> PossibleValues {get; set;}
public string SelectedValue {get; set;}
Load the values into PossibleValues in your ViewModel's constructor.
In the View:
#Html.DropDownListFor(x => x.SelectedValue, new SelectList(Model.PossibleValues))
This will autogenerate your dropdown list and bind it to your model. You can pass default values and other customizations into this Html helper function too, if you want.
Saving Other Values
You can save other values, values which the user shouldn't have the option to edit but which aren't mission-critical if the user does edit, with
#Html.HiddenFor(m => m.RememberThisValue);
Remember, this value is hidden from display but can still be edited on the DOM and posted with whatever the user wants. Make sure you protect yourself from malicious value injection by checking POST'd hidden values.
Store everything important on the server-side, pass a hash/private key in to the user through your model, and implement a static session dictionary to store these small bits of information.

Related

How to deal with postbacks from multiple strongly-typed submit-able partial views on one view?

<%# Page Language="C#" MasterPageFile="~/Views/Shared/MasterPage.Master" Inherits="System.Web.Mvc.ViewPage<EAZYITT_LOGIN.Models.CombinedViewModel>" %>
<asp:Content ContentPlaceHolderID="TitleContent" runat="server">
LoginPage
</asp:Content>
<asp:Content ContentPlaceHolderID="MainContent" runat="server">
<div id="LoginWindow">
<% Html.RenderPartial("LoginWindow", ViewData.Model.Logon); %>
<a id="ForgetPassword" href="#" onclick="loadSegment()">Forgot Password</a>
</div>
<div id="PassReminderWindow">
<% Html.RenderPartial("ReminderWindow", ViewData.Model.Reminder); %>
</div>
</asp:Content>
Each partial view is strongly typed with separate postbacks to the server
Login:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<EAZYITT_LOGIN.Models.LogOnModel>" %>
<div id="loginPage">
<h2>Login Page</h2>
<h3>Submit your credentials to continue or register</h3>
<%: Html.ActionLink("New Registration", "Register")%>
<%: Html.ValidationSummary(true)%>
<%: Html.ValidationSummary()%>
<div class="validation-summary-errors">
<span id="loginError"></span>
</div>
<% using (Html.BeginForm("LoginWindow","Account",FormMethod.Post)) { %>
<%:Html.LabelFor(m =>m.EmailAddress) %>
<%:Html.ValidationMessageFor(m => m.EmailAddress) %>
<%:Html.TextBoxFor(m => m.EmailAddress) %>
<%:Html.LabelFor(m =>m.Password) %>
<%:Html.ValidationMessageFor(m => m.Password) %>
<%:Html.PasswordFor(m => m.Password)%>
<%:Html.CheckBoxFor(m => m.RememberMe)%>
<%:Html.LabelFor(m => m.RememberMe)%>
<p>
<input type="submit" value="Log On" />
</p>
<% } %>
</div>
Password Reminder:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<EAZYITT_LOGIN.Models.ReminderModel>"%>
<div id="PasswordReminderDiv">
<h2>PasswordReminder</h2>
<%: Html.ValidationSummary(true) %>
<div class="validation-summary-errors"><span
id="reminderError"></span></div>
<% using (Html.BeginForm("PasswordReminder",
"Account",FormMethod.Post))
{ //'8' o-o +:: %>
<%:Html.LabelFor(m=>m.ReminderEmailAddress) %>
<%:Html.ValidationMessageFor(m =>
m.ReminderEmailAddress)%>
<%:Html.TextBoxFor(m => m.ReminderEmailAddress) %>
<p>
<input type="submit" value="Send Reminder" />
</p>
<%} %>
</div>
The results are submitted to their separate methods in the controller:
[HttpGet]
public ActionResult Login()
{
CombinedViewModel cModel = new CombinedViewModel();
cModel.Logon = new LogOnModel();
cModel.Reminder = new ReminderModel();
return View(cModel);
}
[HttpPost]
public ActionResult Login(CombinedViewModel _login)
{
return View(_login);
}
[HttpGet]
public ActionResult LoginWindow()
{
return PartialView();
}
[HttpPost]
public ActionResult LoginWindow(LogOnModel _login)
{
if (ModelState.IsValid)
{
if (LoginService.ValidateUser(siteId, _login.EmailAddress, _login.Password))
{
//Goto Next Page
ModelState.AddModelError("loginError", "LOGIN - OK");
}
else
{
//Failed Login
ModelState.AddModelError("loginError", "Wrong username or password");
}
}
return PartialView("LoginWindow", _login);
}
[HttpGet]
public ActionResult PasswordReminder()
{
return View();
}
[HttpPost]
public ActionResult PasswordReminder(ReminderModel _reminder)
{
TempData["ModelState"] = ModelState;
if (LoginService.ValidateNewUser(siteId, _reminder.ReminderEmailAddress))
ModelState.AddModelError("reminderError", "The E-mail address does not exist");
if (ModelState.IsValid)
{
ModelState.AddModelError("reminderError", "E-mail found, send e-mail to user");
}
return PartialView("PasswordReminder",_reminder);
}
Ideally, I would like the main view (Login.aspx) to be displayed regardless of the validation.
However, I've currently got the validation on each partial view working, BUT it is taking me to their separate partial views on failed validation as opposed to the main view.
How would I get it to update the partial view only? Is this the way to do it or should I be using AJAX?
The only way to update the partial view only is AJAX, use AJAX.BeginForm or use JQuery. Otherwise, it expects to go through the full lifecycle.
HTH.

Debugging code in a view (asp.net mvc2)

How do I debug code in the View in asp.net mvc2 application?
Edit after progress last night:
Ok so now I have the following:
in Shared\EditorTemplates\Equipment.ascx :
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<DAT.Models.Item>" %>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<div class="editor-label">
<%: Html.Label("Item ID") %>
<%: Html.TextBoxFor(model => model.ItemID) %>
<%: Html.ValidationMessageFor(model => model.ItemID) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.ModelID) %>
<%: Html.DropDownListFor(x => x.Model.Model1, new SelectList(Model.Model.Model1, "ModelId", "Model", Model.ModelID)) %>
<%: Html.ValidationMessageFor(model => model.ModelID) %>
</div>
...
in Item\Edit.aspx :
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<DAT.ViewModels.ItemEditViewModel>" %>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<%: Html.EditorFor(model => model.Item) %>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
The controller:
public ActionResult Edit(int id)
{
var models = from p in database.Models.Where(x => x.Model1 != null) select p;
var viewModel = new ViewModel
{
Things = database.Things.Single(a => a.ItemID == id),
//tried this:
//Models = database.Models
Models = models
};
return View(viewModel);
}
So I am sure that the problem is with this line
<%: Html.DropDownListFor(x => x.Model.Model1, new SelectList(Model.Model.Model1, "ModelId", "Model", Model.ModelID)) %>
When generating the selectlist, I don't have IEnumerable for the first parameter? Or one of the values I am feeding this is causing null. How do I get the list of models in my view?
EDIT AFTER PULLING ALL MY HAIR OUT:
It seems the problem lies in this example: http://www.asp.net/mvc/tutorials/mvc-music-store-part-4 . Strangely, I am not sure if it is following best practice. Look at the code and how they pass the models about - it seems stupidly obscure using ViewData["Blah"] and the Models as well, why can't you just have it all sent as the model? Look at the code how they have done it:
Album.ascx :
<%# Import Namespace="MvcMusicStore"%>
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcMusicStore.Models.Album>" %>
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcValidation.js" type="text/javascript"></script>
<p>
<%: Html.LabelFor(model => model.Title)%>
<%: Html.TextBoxFor(model => model.Title)%>
<%: Html.ValidationMessageFor(model => model.Title)%>
</p>
<p>
<%: Html.LabelFor(model => model.Price)%>
<%: Html.TextBoxFor(model => model.Price)%>
<%: Html.ValidationMessageFor(model => model.Price)%>
</p>
<p>
<%: Html.LabelFor(model => model.AlbumArtUrl)%>
<%: Html.TextBoxFor(model => model.AlbumArtUrl)%>
<%: Html.ValidationMessageFor(model => model.AlbumArtUrl)%>
</p>
<p>
<%: Html.LabelFor(model => model.Artist)%>
<%: Html.DropDownList("ArtistId", new SelectList(ViewData["Artists"] as IEnumerable, "ArtistId", "Name", Model.ArtistId))%>
</p>
<p>
<%: Html.LabelFor(model => model.Genre)%>
<%: Html.DropDownList("GenreId", new SelectList(ViewData["Genres"] as IEnumerable, "GenreId", "Name", Model.GenreId))%>
</p>
View:
<%# Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcMusicStore.ViewModels.StoreManagerViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Edit - <%: Model.Album.Title %>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Edit Album</h2>
<% Html.EnableClientValidation(); %>
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Edit Album</legend>
<%: Html.EditorFor(model => model.Album, new { Artists = Model.Artists, Genres = Model.Genres}) %>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
<div>
<%:Html.ActionLink("Back to Albums", "Index") %>
</div>
</asp:Content>
View Model:
using System.Collections.Generic;
using MvcMusicStore.Models;
namespace MvcMusicStore.ViewModels
{
public class StoreManagerViewModel
{
public Album Album { get; set; }
public List<Artist> Artists { get; set; }
public List<Genre> Genres { get; set; }
}
}
And the controller:
//
// GET: /StoreManager/Edit/5
public ActionResult Edit(int id)
{
var viewModel = new StoreManagerViewModel
{
Album = storeDB.Albums.Single(a => a.AlbumId == id),
Genres = storeDB.Genres.ToList(),
Artists = storeDB.Artists.ToList()
};
return View(viewModel);
}
So it looks to me like the model is built in the controller as makes logical sense to me. Then in the view they use this statement which causes my confusion:
<%: Html.EditorFor(model => model.Album, new { Artists = Model.Artists, Genres = Model.Genres}) %>
The model is being split/changed and now we send the other (Artists, Genres) as ViewData ??
Can someone explain, and is this at all fitting with the entire design pattern?
You could put a breakpoint in your controller action and analyze your model and view data.
This being said, why are you using a strongly typed view and ViewData at the same time? Make sure that ViewData["Models"] as IEnumerable is not null (in your controller) or even better get rid of it and put it in your model as a strongly typed property. Also I would recommend you using the strongly typed helper DropDownListFor:
<%: Html.DropDownListFor(
x => x.ModelID,
new SelectList(Model.Models, "ModelId", "Model", Model.ModelID)
)%>

Help me create a dropdownlist of all Jefes in my database!

I have the following table structure:
I'm trying to populate a combobox of all the Jefes when editing an Area. Meaning I can change who's in charge of an area.
Here is my AreaController.cs code:
public ActionResult Edit(int id)
{
Area area = areaRepository.GetArea(id);
JefeRepository jefe = new JefeRepository();
ViewData["Jefes"] = new SelectList(jefe.FindAllJefes(), "Nombre", "Nombre");
return View(area);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues)
{
Area area = areaRepository.GetArea(id);
try
{
UpdateModel(area);
areaRepository.Save();
return RedirectToAction("Details", new { id = area.ID });
}
catch (Exception)
{
foreach (var issue in area.GetRuleViolations())
{
ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
}
return View(area);
}
}
Note that .FindAllJefes() returns an IQueryable<> collection.
Now in my Edit.aspx file I have the following:
<fieldset>
<legend>Informacion Detallada de Area | <%: Model.Nombre %></legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Nombre) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Nombre) %>
<%: Html.ValidationMessageFor(model => model.Nombre) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.IDJefe) %>
</div>
<div class="editor-field">
<%: Html.DropDownList("IDJefe", (SelectList)ViewData["Jefes"], "(Select Jefe)") %>
<%: Html.ValidationMessageFor(model => model.IDJefe) %>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
I receive this error:
There is no ViewData item of type
'IEnumerable' that has
the key 'IDJefe'.
Per MSDN :
new SelectList(jefe.FindAllJefes(), "Nombre", "Nombre");
jefe.FindAllJefes() should be an IEnumerable when passed to a SelectList ctor. Your argument which should read jefe.FindAllJefes().ToList()
Without seeing how your custom classes are designed, this is a tough one, but just to hazard a guess:
ViewData["Jefes"] = new SelectList(jefe.FindAllJefes(), "Nombre", "Nombre")
I don't know how your SelectList class is setup, but (maybe) you're using "Nombre" as the ID AND the display value (???).
So your select list is looking for a key called "IDJefe", and not finding it, because you used "Nombre" twice.
<div class="editor-field">
<%: Html.DropDownList("IDJefe", (SelectList)ViewData["Jefes"], "(Select Jefe)") %>
<%: Html.ValidationMessageFor(model => model.IDJefe) %>
</div>

Problems with Partial Views in ASP.NET MVC 2

this is the master page :
<%# Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
<link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
<asp:ContentPlaceHolder ID="header1" runat="server" />
</head>
<body>
<div class="page">
<div id="header">
<div id="title">
<h1>My MVC Application</h1>
</div>
<div id="logindisplay">
<% Html.RenderPartial("LogOnUserControl"); %>
</div>
<div id="menucontainer">
<ul id="menu">
<li><%= Html.ActionLink("Home", "Index", "Home")%></li>
<li><%= Html.ActionLink("About", "About", "Home")%></li>
<li><%= Html.ActionLink("Imoveis", "Index", "Categoria")%></li>
<li><%= Html.ActionLink("Admin", "Index", "Admin")%></li>
<li><%= Html.ActionLink("User", "Index", "User")%></li>
</ul>
</div>
</div>
<div id="left">
<% Html.RenderPartial("~/Views/Imovel/Pesquisa.ascx"); %>
</div>
<div id="main">
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
<div id="footer">
</div>
</div>
</div>
</body>
</html>
Partial View
<%= Html.DropDownList("categoria_id", (SelectList)ViewData["Categoriass"], "--Selecciona um--")%>
<div class="editor-label">
<%= Html.LabelFor(model => model.categoria_id) %>
</div>
<div class="editor-field">
<%= Html.DropDownListFor(model => model.categoria_id, (SelectList)ViewData["Categorias"], "--Selecciona um--")%>
<%= Html.ValidationMessageFor(model => model.categoria_id) %>
</div>
This is the problem:
public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
**ViewData["Categoriass"] = new SelectList(catRepository.FindAllCategorias().AsEnumerable(), "id", "nome", 3);**
return View();
}
Since the partial view is in the master page, how do I get its model?
I think you should create an ActionFilter and apply it on your controllers.
Create an action filter like this
public class DataForMasterPageAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//initiate your repository
var catRepository = ...;
//then create the viewdata like so
filterContext.Controller.ViewData["Categorias"] = new SelectList(catRepository.FindAllCategorias().AsEnumerable(), "id", "nome", 3);
}
}
Then apply it on the controller and it will be available for all actions as well. Like so;
[DataForMasterPage]
public class CategoriaController : Controller
{
public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View();
}
}
On the partial view you just call the ViewData as usual, no need to change anything
<div class="editor-label">
<%= Html.LabelFor(model => model.categoria_id) %>
</div>
<div class="editor-field">
<%= Html.DropDownListFor(model => model.categoria_id, (SelectList)ViewData["Categorias"], "--Selecciona um--")%>
<%= Html.ValidationMessageFor(model => model.categoria_id) %>
</div>
Might have performance issues, but its one of the simplest ways to avoid setting the ViewData on every method.
You can create base class for your controllers and set it during creation if you need to query for it with every request:
public class BaseController : Controller
{
public BaseController()
{
var catRepository = ...;
ViewData["Categoriass"] = new SelectList(catRepository.FindAllCategorias().AsEnumerable(), "id", "nome", 3);
}
}
That is not really efficient,because it will be executed with every controller. You can also create action filter which sets ViewData and apply it where needed.
I have try Nick Masao & LukLed solutions, both of them are works.
However, the viewdata is set for masterpage, in my case, i assume masterpage will render every page.
I have to
apply the [DataForMasterPage] attribute (Nick Masao's solutions) or
or
inherits the BaseController (LukLed's solutions)
on every View's Controller.
So, is it possible create a Class and invoke on Global.asax Application_Start event to make it Set viewdata everytimes?
You could also create a ContentPlaceHolder where you want the partial view to render and call the RenderPartial() from the underlying pages. That way you can pass the model as usual.

Calling SubmitChanges on DataContext does not update database

In C# ASP.NET MVC application I use Link to SQL to provide data for my application. I have got simple database schema like this:
In my controller class I reference this data context called Model (as you can see on the right side of picture in properties) like this:
private Model model = new Model();
I've got a table (List) of Series rendered on my page. It renders properly and I was able to add delete functionality to delete Series like this:
public ActionResult Delete(int id) {
model.Series.DeleteOnSubmit(model.Series.SingleOrDefault(s => s.ID == id));
model.SubmitChanges();
return RedirectToAction("Index");
}
Where appropriate action link looks like this:
<%: Html.ActionLink("Delete", "Delete", new { id=item.ID })%>
Also create (implemented in similar way) works fine. However edit does not work. My edit looks like this:
public ActionResult Edit(int id) {
return View(model.Series.SingleOrDefault(s => s.ID == id));
}
[HttpPost]
public ActionResult Edit(Series series) {
if (ModelState.IsValid) {
UpdateModel(series);
series.Title = series.Title + " some string to ensure title has changed";
model.SubmitChanges();
return RedirectToAction("Index");
}
return View(series);
}
I have controlled that my database has a primary key set up correctly. I debugged my application and found out that everything works as expected until the line with model.SubmitChanges();. This command does not apply the changes of Title property(or any other) against the database.
Please help.
EDIT:
If I add this line: model.Series.Attach(series); just before model.SubmitChanges(); there is no change - edits still does not reflect to database. The instance passed to Edit method as a parameter is already attached to the data context model.
EDIT:
Code of view that belongs to method Edit:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<TVSeriesInfoApp.Models.Series>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Edit
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Edit</h2>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Title) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Title) %>
<%: Html.ValidationMessageFor(model => model.Title) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Seasons) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Seasons) %>
<%: Html.ValidationMessageFor(model => model.Seasons) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Stars) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Stars) %>
<%: Html.ValidationMessageFor(model => model.Stars) %>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Index") %>
</div>
</asp:Content>
This is what our Edit Action would look like (Adjusted for your model):
[HttpPost]
public ActionResult Edit(int id, Series series)
{
Series updatingSeries = model.Series.Single(s => s.ID == id);
try
{
TryUpdateModel(updatingSeries);
model.SubmitChanges();
return RedirectToAction("Details", new { id = updatingSeries.ID });
}
catch
{
return View(updatingSeries);
}
}
This can happen because the ModelState might not be valid in some cases. Have you done something to the View? Can you also post your View Code here please?
First, never ever "delete" with HTTP GET (this is exactly what you're doing with Html.ActionLink("Delete", "Delete", new { id=item.ID }).
As for edits, you first have to Attach your instance to the DataContext.

Categories

Resources