I am trying to make a dropdown box in ASP.NET, when the View is generated it gives me an error saying Categorie_ID is not found in Model Categorie (it does exist and it's public and all). The categories and product are succesfully being loaded (I have debugged that part).
Here's what I got;
My view:
#{
ViewBag.Title = #Model.Product.Merk; #Model.Product.Type;;
Layout = "~/Views/Shared/_Layout.cshtml";
}
#model WebshopProjectBlokC.ViewModels.ProductViewModel
<h2>#Model.Product.Merk #Model.Product.Type wijzigen</h2>
#using (Html.BeginForm("ProductWijzigenForm", "ProductBeheer"))
{
#Html.ValidationSummary(true)
<fieldset>
#Html.HiddenFor(model => model.Product.ID)
#Html.HiddenFor(model => model.Product.Naam)
<div class="editor-label">Prijs</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Product.Prijs)
#Html.ValidationMessageFor(model => model.Product.Prijs)</div>
<div class="editor-label">Maat</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Product.Maat)
#Html.ValidationMessageFor(model => model.Product.Maat)</div>
<div class="editor-label">Merk</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Product.Merk)
#Html.ValidationMessageFor(model => model.Product.Merk)</div>
<div class="editor-label">Type</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Product.Type)
#Html.ValidationMessageFor(model => model.Product.Type)</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.SelectedID, Model.Categorien)
</div>
<div class="editor-label">URL Foto</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Product.Afbeelding)
#Html.ValidationMessageFor(model => model.Product.Afbeelding)</div>
<input type="submit" value="Wijzig" />
</fieldset>
}
The controller:
public ActionResult ProductWijzig(int productid)
{
ProductViewModel viewModel = new ProductViewModel();
Product product = ProductdataController.GetProduct(productid);
List<Categorie> catas = ProductdataController.HaalCategorienOp();
viewModel.Categorien = new SelectList(catas, "Categorie_id", "Naam");
viewModel.Product = product;
return View(viewModel);
}
The viewmodel:
namespace WebshopProjectBlokC.ViewModels
{
public class ProductViewModel
{
public Product Product { get; set; }
public Categorie Categorie { get; set; }
public SelectList Categorien { get; set; }
public int SelectedID { get; set; }
}
}
The HaalCategorienOp method;
public List<Categorie> HaalCategorienOp()
{
List<Categorie> categorien = new List<Categorie>();
try
{
conn.Open();
string selecteer = "select * from categorie";
MySqlCommand command = new MySqlCommand(selecteer, conn);
MySqlDataReader dataReader = command.ExecuteReader();
while (dataReader.Read())
{
Categorie categorie = HaalCategorieUitReader(dataReader);
categorien.Add(categorie);
}
}
catch (Exception e)
{
Console.Write("Ophalen van categorien mislukt " + e);
throw e;
}
finally
{
conn.Close();
}
return categorien;
}
HaalCategorieUitReader method;
protected Categorie HaalCategorieUitReader(MySqlDataReader datareader)
{
if (!datareader.IsDBNull(0))
{
categorie_id = datareader.GetInt32("categorie_id");
}
if (!datareader.IsDBNull(1))
{
categorienaam = datareader.GetString("naam");
}
if (!datareader.IsDBNull(2))
{
hoofdcategorie = datareader.GetInt32("hoofdcategorie");
}
Categorie categorie = new Categorie{ Categorie_id = categorie_id, Hoofdcategorie = hoofdcategorie, Naam = categorienaam};
return categorie;
}
Related
I am using ASP.Net MVC, I am trying to get values using a ViewModel.
FAQ class have (Name,Description)
FAQ_Detail class is List of Question and Answer which I am passing as PartialView
I have attached front end page and controller page, in controller I can get the Name,Description but always return NULL FAQ_Detail property
View Model
public class FAQViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public IList<Details> FAQ_Details { get; set; }
}
public class Details
{
public int Id { get; set; }
public int FAQId { get; set; }
public string Question { get; set; }
public string Answer { get; set; }
}
View
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>FAQ</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Description, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Description, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Description, "", new { #class = "text-danger" })
</div>
</div>
<br />
<br />
<br />
#for (int i = 0; i <= 2; i++)
{
var m = new FAQ.Models.ViewModels.Details()
{
Id = i,
FAQId = 11,
Question = string.Format("Quesiton {0}",i),
Answer = string.Format("Ans. {0}",i)
};
#Html.Partial("_AddFAQ",m)
}
<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>
}
Controller
[HttpPost]
public ActionResult Create(Models.ViewModels.FAQViewModel model) //The model.FAQ_Details array always empty
{
try
{
//
return RedirectToAction("Index");
}
catch
{
return View();
}
}
The problem is you are just displaying the question/answer pair as form fields and there is nothing to bind them to the array in the model you expect. Usually, the name HTML attribute maps the client-side field to the property name of the model on the server.
The better thing you can do is to have some JavaScript, collect the data and pass that through an AJAX call to the server.
I found a solution, I pass master model in controller and use Detail model as collection
public ActionResult Create(string name,string description, ICollection<Models.ViewModels.Details> data)
{
try
{
//
return RedirectToAction("Index");
}
catch
{
return View();
}
}
Above is a picture of my edit page. The issue I have is that this editor (summernote) does not persist it's data when I save
**I have however, narrowed down the problem. **
Fields on the form persist the data in the value field on the HTML elements
SummerNote does not store the text I've written into the editor in the value element
If I use the default editor and put a value in (which is stored in the value element), then use summernote, the value in the value field will be there, but not displayed.
Editing this value field in the inspector will then cause the value to be persisted on save.
The line containing the value field:
<input class="form-control text-box single-line" id="Content_Content" name="Content.Content" type="text" value="I am the text that is not shown but would be persisted!" style="display: none;">
The note-editing-area div:
<div class="note-editing-area"><div class="note-handle"><div class="note-control-selection" style="display: none;"><div class="note-control-selection-bg"></div><div class="note-control-holder note-control-nw"></div><div class="note-control-holder note-control-ne"></div><div class="note-control-holder note-control-sw"></div><div class="note-control-sizing note-control-se"></div><div class="note-control-selection-info"></div></div></div><textarea class="note-codable"></textarea><div class="note-editable panel-body" contenteditable="true" style="height: 320px;"><h1>Help!</h1><p>What I type here will not be persisted when i click the <b>save </b>button.</p></div></div>
My question therefore is this:
How can I Either
Have the html between the ::before and ::after of the summernote editor (The value that the user types into the control) be put into the value tag aswell so that it is persisted
Do something else to make it work.
Additional Information:
Here is My Model:
Article.cs:
public class Article
{
#region Constructors
public Article(string title, string subTitle = "")
{
InitializeCollections();
Title = title;
SubTitle = subTitle;
}
public Article(string title, Article parentArticle, string subTitle = "")
{
InitializeCollections();
Title = title;
SubTitle = subTitle;
ParentArticles.Add(parentArticle);
}
public Article()
{
InitializeCollections();
}
void InitializeCollections()
{
ParentArticles = new List<Article>();
ChildArticles = new List<Article>();
}
#endregion
[Key]
public int ArticleId { get; set; }
public virtual ArticleContent Content { get; set; }
[StringLength(GUIConstants.MaxCharactersInMenuItemText)]
public string Title { get; set; }
[StringLength(100)]
public string SubTitle { get; set; }
public int? Sequence { get; set; }
public bool Published { get; set; }
public DateTime? PublishedDate { get; set; }
public virtual ICollection<Article> ParentArticles { get; set; }
public virtual ICollection<Article> ChildArticles { get; set; }
public string Notes { get; set; }
Article Content (It's the Content's Content property that has the WYSIWYG Editor, however if i use the WYSIWYG for a property dirrectly on the article model (like Title) I get the same issue.
public class ArticleContent
{
[Key, ForeignKey("Article")]
public int ArticleId { get; set; }
public virtual Article Article { get; set; }
[AllowHtml]
public string Content { get; set; }
}
}
Controller:
// GET: Articles/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var article = db.Article.Include(a => a.Content).SingleOrDefault(a => a.ArticleId == id);
if (article == null)
{
return HttpNotFound();
}
return View(article);
}
// POST: Articles/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.
[ValidateInput(false)]
[HttpPost, ActionName("Edit")]
public ActionResult EditPost(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var articleToUpdate = db.Article.Include(a => a.Content).SingleOrDefault(a => a.ArticleId == id);
if (TryUpdateModel(articleToUpdate, "",
new string[] { "Title", "SubTitle", "Sequence", "Content" }))
{
try
{
db.SaveChanges();
return RedirectToAction("Index");
}
catch (RetryLimitExceededException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
}
return View(articleToUpdate);
}
View:
**#model Catalyst.Models.Article
#{
ViewBag.Title = "Edit Article";
}
#section styles{
#Styles.Render("~/Content/summernote")
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.ArticleId)
<div class="form-group">
#Html.LabelFor(model => model.Title, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Title, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Title, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SubTitle, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.SubTitle, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.SubTitle, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Sequence, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Sequence, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Sequence, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Content.Content, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Content.Content, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Content.Content, "", 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", "Articles", new { #class = "btn btn-default" })
</div>
#section scripts {
#Scripts.Render("~/bundles/SummerNote", "~/bundles/SummerNoteArticleContentEditor")
}**
The Javascript turning the content textbox into summernote
(function ($) {
function HomeIndex() {
var $this = this;
function initialize() {
$('#Content_Content').summernote({
focus: true,
height: 320,
codemirror: {
theme: 'united'
}
});
}
$this.init = function () {
initialize();
}
}
$(function () {
var self = new HomeIndex();
self.init();
})
}(jQuery))
I followed this guide:
http://www.c-sharpcorner.com/UploadFile/3d39b4/bootstrap-wysiwyg-editor-in-Asp-Net-mvc/
I adding an admin area to an Asp.net MVC4 Application and I would consider myself a entry-level developer. My edit [HttpGet] action is working fine as it returns the values of asset. I have poured through a bunch of MVC4 specials online and most of them use the following for [HttpPost] Edit method:
[HttpPost]
public ActionResult Edit(ITTESI.AssetTracker.Web.UI.ViewModels.AssetDetailsViewModel models)
{
try
{
if (ModelState.IsValid)
{
_entities.Entry(models).State = EntityState.Modified;
_entities.SaveChanges();
return RedirectToAction("Index", new { ID = models.ID });
}
}
catch (DataException)
{
ModelState.AddModelError("", "Unable able to save changes....epic fail!!!");
}
return View(models);
}
The problem is that I do not have access to use .Entry in the following:
_entities.Entry(models).State = EntityState.Modified;
I am obviously missing a reference that will enable me to use it, but I am not sure what it is.
Here is my ViewModel(I would have used DbContext, but they did not):
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using ITTESI.AssetTracker.Web.UI.Content.Classes;
namespace ITTESI.AssetTracker.Web.UI.ViewModels
{
public class AssetDetailsViewModel
{
public int ID { get; set; }
public string AssetIdentifier { get; set; }
public string ManufacturerName { get; set; }
public string Model { get; set; }
public string SchoolLocation { get; set; }
public string Status { get; set; }
public string Condition { get; set; }
// [DataType(DataType.MultilineText)]
public string Notes { get; set; }
public Utils.AssignReturn AssignReturnEligible { get; set; }
public string SchoolLocationCd { get; set; }
public string SchoolLocationDisplayValue { get; set; }
public AssignedUserViewModel AssignedUserViewModelObj { get; set; }
}
}
Here is my Admin Controller:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Metadata.Edm;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using ITTESI.AssetTracker.Data.EntityModel.Entity;
using ITTESI.AssetTracker.Data.EntityModel.Definition;
using System.Data.Entity;
using ITTESI.AssetTracker.Web.UI;
using ITTESI.AssetTracker.Web.UI.Content;
using ITTESI.AssetTracker.Web.UI.Content.Classes;
using ITTESI.AssetTracker.Web.UI.ViewModelBuilders;
using ITTESI.AssetTracker.Web.UI.ViewModels;
namespace ITTESI.AssetTracker.Web.UI.Controllers
{
public class AdminController : Controller
{
ExtendedITTESI_AssetTrackerEntities _entities = new ExtendedITTESI_AssetTrackerEntities();
public ActionResult Index(ViewModels.AssetDetailsViewModel assetDetails)
{
ViewBag.PageTitle = "Admin Search";
ViewBag.HideShowLocation = "hide";
ViewBag.SubmitButtonValue = "Search";
return View("Index", assetDetails);
}
[HttpGet]
public ActionResult Edit(ITTESI_AssetTracker_Asset asset) // 'ITTESI.AssetTracker.Web.UI.ViewModels.AssetDetailsViewModel'
{
ViewBag.PageTitle = "Edit Asset";
ViewBag.SubmitButtonValue = "Save";
ViewBag.ShowLocation = true;
var model = _entities.ITTESI_AssetTracker_Asset.FirstOrDefault();
return View(model);
}
[HttpPost]
//public ActionResult Edit(ExtendedITTESI_AssetTrackerEntities ate)
public ActionResult Edit(ITTESI.AssetTracker.Web.UI.ViewModels.AssetDetailsViewModel models)
{
try
{
if (ModelState.IsValid)
{
_entities.Entry(models).State = EntityState.Modified;
_entities.SaveChanges();
return RedirectToAction("Index", new { ID = models.ID });
}
}
catch (DataException)
{
ModelState.AddModelError("", "Unable able to save changes....epic fail!!!");
}
return View(models);
}
}
}
Here is my Edit View:
#model ITTESI.AssetTracker.Data.EntityModel.Entity.ITTESI_AssetTracker_Asset
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>ITTESI_AssetTracker_Asset</legend>
#Html.HiddenFor(model => model.ID)
<div class="editor-label">
#Html.LabelFor(model => model.AssetIdentifier)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AssetIdentifier)
#Html.ValidationMessageFor(model => model.AssetIdentifier)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AssetConditionID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AssetConditionID)
#Html.ValidationMessageFor(model => model.AssetConditionID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.SchoolID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.SchoolID)
#Html.ValidationMessageFor(model => model.SchoolID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AssetCategoryID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AssetCategoryID)
#Html.ValidationMessageFor(model => model.AssetCategoryID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.VendorID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.VendorID)
#Html.ValidationMessageFor(model => model.VendorID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AssignedPersonID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AssignedPersonID)
#Html.ValidationMessageFor(model => model.AssignedPersonID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AssetStatusID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AssetStatusID)
#Html.ValidationMessageFor(model => model.AssetStatusID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ManufacturerID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ManufacturerID)
#Html.ValidationMessageFor(model => model.ManufacturerID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ModelDetail)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ModelDetail)
#Html.ValidationMessageFor(model => model.ModelDetail)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.CreatedOn)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CreatedOn)
#Html.ValidationMessageFor(model => model.CreatedOn)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.CreatedByIdentifier)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CreatedByIdentifier)
#Html.ValidationMessageFor(model => model.CreatedByIdentifier)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ModifiedOn)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ModifiedOn)
#Html.ValidationMessageFor(model => model.ModifiedOn)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ModifiedByIdentifier)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ModifiedByIdentifier)
#Html.ValidationMessageFor(model => model.ModifiedByIdentifier)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Notes)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Notes)
#Html.ValidationMessageFor(model => model.Notes)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
I also certain the problem is that DbContext for ExtendedITTESI_AssetTrackerEntities does not exist and after research a bit more that is part of the System.Data.Entity. The only code I have for ExtendedITTESI_AssetTrackerEntities is:
using System;
using Common.Logging;
using EFCachingProvider;
using EFCachingProvider.Caching;
using EFProviderWrapperToolkit;
using EFTracingProvider;
using ITTESI.AssetTracker.Data.EntityModel.Entity;
namespace ITTESI.AssetTracker.Data.EntityModel.Definition
{
public class ExtendedITTESI_AssetTrackerEntities : ITTESI_AssetTrackerEntities
{
private ILog logOutput;
public ExtendedITTESI_AssetTrackerEntities()
: this("name=ITTESI_AssetTrackerEntities")
{
}
public ExtendedITTESI_AssetTrackerEntities(string connectionString)
: base(EntityConnectionWrapperUtils.CreateEntityConnectionWithWrappers(
connectionString,
"EFTracingProvider",
"EFCachingProvider"
))
{
CachingPolicy = AssetTrackerEntitiesCachingPolicy.CachingPolicy();
Cache = AssetTrackerEntitiesCache.Cache();
}
#region Tracing Extensions
private EFTracingConnection TracingConnection
{
get { return this.UnwrapConnection<EFTracingConnection>(); }
}
public event EventHandler<CommandExecutionEventArgs> CommandExecuting
{
add { this.TracingConnection.CommandExecuting += value; }
remove { this.TracingConnection.CommandExecuting -= value; }
}
public event EventHandler<CommandExecutionEventArgs> CommandFinished
{
add { this.TracingConnection.CommandFinished += value; }
remove { this.TracingConnection.CommandFinished -= value; }
}
public event EventHandler<CommandExecutionEventArgs> CommandFailed
{
add { this.TracingConnection.CommandFailed += value; }
remove { this.TracingConnection.CommandFailed -= value; }
}
private void AppendToLog(object sender, CommandExecutionEventArgs e)
{
if (this.logOutput != null)
{
this.logOutput.Debug(e.ToTraceString().TrimEnd());
}
}
public ILog Log
{
get { return this.logOutput; }
set
{
if ((this.logOutput != null) != (value != null))
{
if (value == null)
{
CommandExecuting -= AppendToLog;
}
else
{
CommandExecuting += AppendToLog;
}
}
this.logOutput = value;
}
}
#endregion
#region Caching Extensions
private EFCachingConnection CachingConnection
{
get { return this.UnwrapConnection<EFCachingConnection>(); }
}
public ICache Cache
{
get { return CachingConnection.Cache; }
set { CachingConnection.Cache = value; }
}
public CachingPolicy CachingPolicy
{
get { return CachingConnection.CachingPolicy; }
set { CachingConnection.CachingPolicy = value; }
}
#endregion
}
}
I might have to create a model with DbContext is that fair to say?
Can I use anything besides .Entry? I appreciate the help, but with the way the app is set up I am not sure how to properly save edits back to the database.
there is a way besides .Entry for the Edit Action. EF is very clever, you can just fetch the object by ID form the database and change all the properties manually.
Ex:
[HttpPost]
public ActionResult Edit(ITTESI.AssetTracker.Web.UI.ViewModels.AssetDetailsViewModel models)
{
try
{
if (ModelState.IsValid)
{
ITTESI.AssetTracker.Web.UI.ViewModels.AssetDetailsViewModel temp = _entities.dbname.firstOrDefault(x = > x.ID == models.ID);
temp.AssetIdentifier = models.AssetIdentifier ;
temp.ManufacturerName = models.ManufacturerName ;
.
.
.
_entities.SaveChanges();
return RedirectToAction("Index", new { ID = models.ID });
}
}
catch (DataException)
{
ModelState.AddModelError("", "Unable able to save changes....epic fail!!!");
}
return View(models);
}
EF will understand what entity you want to modify, and will update it with "_entities.saveChanges();"
I don't really know that this will work for you, but I think it's worth trying
I'm trying to create ASP.NET MVC Application with Entity Framework, which has One to Many relationship. For that I have successfully managed to load the appropriate list of items to a dropdown control (in Create view), But when I click the Create button (in Create view) page validation is faild, validation error message is The value '1' is invalid..
Error
Model
public class Post
{
public int Id { get; set; }
...
public virtual Person Author { get; set; }
}
DataBaseContext
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Post>()
.HasOptional(p => p.Author);
}
Controller
public ActionResult Create()
{
PopulateAuthorDropDownList();
return View();
}
[HttpPost]
public ActionResult Create(Post post)
{
if (ModelState.IsValid)
{
db.Posts.Add(post);
db.SaveChanges();
return RedirectToAction("Index");
}
PopulateAuthorDropDownList(post.Author);
return View(post);
}
private void PopulateAuthorDropDownList(object selectedPerson = null)
{
var personQuery = from d in db.People
orderby d.Name
select d;
ViewBag.Author = new SelectList(personQuery, "Id", "Name", selectedPerson);
}
View
<div class="editor-label">
#Html.LabelFor(model => model.Author)
</div>
<div class="editor-field">
#Html.DropDownList("Author", String.Empty)
#Html.ValidationMessageFor(model => model.Author)
</div>
When I check Author table in database there is Record with Id 1, so I guess 1 is a valid value. What am I missing here?
Thanks in advance...
You didn't show how the Author object looks like,
Suppose if it is like this,
public class Author
{
public int Id{get;set;}
public string Name{get;set;}
}
Try this,
<div class="editor-label">
#Html.LabelFor(model => model.Author)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Author.Id, ViewBag.Author, "Select an Author")
#Html.ValidationMessageFor(model => model.Author)
</div>
Managed to fix this by
changing Model to
public class Post
{
public int Id { get; set; }
...
public int Author { get; set; } // changed type to int
}
changing View to
<div class="editor-label">
#Html.LabelFor(model => model.Author)
</div>
<div class="editor-field">
#Html.DropDownList("AuthorId", String.Empty)
#Html.ValidationMessageFor(model => model.Author)
</div>
changing Controller to
private void PopulateAuthorDropDownList(object selectedPerson = null)
{
var personQuery = from d in db.People
orderby d.Name
select d;
ViewBag.AuthorId = new SelectList(personQuery, "Id", "UserName", selectedPerson); //Changed Author to AuthorId
}
and removing
modelBuilder.Entity<Post>()
.HasOptional(p => p.Author);
from DataBaseContext
Anyway Thanks for the answers... :)
You should have something like this:
<div class="editor-label">
#Html.LabelFor(model => model.Author.Name)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Author.Name, (SelectList)ViewBag.AuthorList)
#Html.ValidationMessageFor(model => model.Author.Name)
</div>
Note that you should name ViewBag.AuthorList instead of ViewBag.Author
You have to provide a list of options to DropDownList where you are just passing string.empty.
And i You should use the strongly typed version DropDownListFor:
#Html.DropDownListFor(model => model.Author.Name, Model.AuthorList)
Or maybe even better by not using the name but the Id:
#Html.DropDownListFor(model => model.Author.Id, Model.AuthorList)
And your model:
class Model {
...
public SelectList AuthorList {get;set;}
}
And in your controller:
model.AuthorList = new SelectList(fetchAuthors()
.Select(a => new SelectListItem {
Text = a.Name,
Value = a.Id
}, "Value", "Text");
I created a content part and then added it to a content type in Orchard. But when I try to create a content item of that type, the fields for the part's properties are not displayed. I'm looking for suggestions of where the problem might be.
UPD: the relevant code:
using JetBrains.Annotations;
using ArealAds.Models;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using ArealAds.Models;
using ArealAds.Services;
using ArealAds.ViewModels;
namespace ArealAds.Drivers {
[UsedImplicitly]
public class AdDriver : ContentPartDriver<AdPart> {
private readonly IAdService _adService;
public AdDriver (IAdService adService)
{
_adService = adService;
}
protected override string Prefix {
get { return "AdPart"; }
}
protected override DriverResult Display(
AdPart part, string displayType, dynamic shapeHelper) {
return ContentShape("Parts_Ad", () => shapeHelper.Parts_Ad(
Title: part.Title,
Url: part.Url,
Email: part.Email,
Phone1: part.Phone1,
Phone2: part.Phone2,
AreaName: part.AreaRecord.Name,
AreaId: part.AreaRecord.Id,
DistrictName: part.DistrictRecord.Name,
DistrictId: part.DistrictRecord.Id,
AllDistricts: part.AllDistricts));
}
//GET
protected override DriverResult Editor(
AdPart part, dynamic shapeHelper) {
return ContentShape("Parts_Ad_Edit",
() => shapeHelper.EditorTemplate(
TemplateName: "Parts/Ad",
Model: BuildEditorViewModel(part),
Prefix: Prefix));
}
//POST
protected override DriverResult Editor(
AdPart part,
IUpdateModel updater,
dynamic shapeHelper) {
var model = new EditAdViewModel();
updater.TryUpdateModel(model, Prefix, null, null);
if (part.ContentItem.Id != 0) {
_adService.Update(
part.ContentItem, model);
}
return Editor(part, shapeHelper);
}
private EditAdViewModel BuildEditorViewModel(AdPart part) {
var avm = new EditAdViewModel {
Title = part.Title,
Url = part.Url,
Email = part.Email,
Phone1 = part.Phone1,
Phone2 = part.Phone2,
AllDistricts = part.AllDistricts,
Areas = _adService.GetAreas(),
Districts = _adService.GetDistricts()
};
if (part.AreaRecord != null) {
avm.AreaName = part.AreaRecord.Name;
avm.AreaId = part.AreaRecord.Id;
}
if (part.DistrictRecord != null) {
avm.DistrictName = part.DistrictRecord.Name;
avm.DistrictId = part.DistrictRecord.Id;
}
return avm;
}
}
}
using System.ComponentModel.DataAnnotations;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Records;
namespace ArealAds.Models {
public class AdRecord : ContentPartRecord {
public virtual string Title { get; set; }
public virtual string Url { get; set; }
public virtual string Email { get; set; }
public virtual string Phone1 { get; set; }
public virtual string Phone2 { get; set; }
public virtual AreaRecord AreaRecord { get; set; }
public virtual DistrictRecord DistrictRecord { get; set; }
public virtual bool AllDistricts { get; set; }
}
public class AdPart : ContentPart<AdRecord> {
[Required]
public string Title {
get { return Record.Title; }
set { Record.Title = value; }
}
public string Url {
get { return Record.Url; }
set { Record.Url = value; }
}
public string Email {
get { return Record.Email; }
set { Record.Email = value; }
}
public string Phone1 {
get { return Record.Phone1; }
set { Record.Phone1 = value; }
}
public string Phone2 {
get { return Record.Phone2; }
set { Record.Phone2 = value; }
}
public AreaRecord AreaRecord {
get { return Record.AreaRecord; }
set { Record.AreaRecord = value; }
}
public DistrictRecord DistrictRecord {
get { return Record.DistrictRecord; }
set { Record.DistrictRecord = value; }
}
[Required]
public bool AllDistricts {
get { return Record.AllDistricts; }
set { Record.AllDistricts = value; }
}
}
}
#model ArealAds.ViewModels.EditAdViewModel
<fieldset>
<legend>Area 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.Url)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Url)
#Html.ValidationMessageFor(model => model.Url)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Email)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Phone1)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Phone1)
#Html.ValidationMessageFor(model => model.Phone1)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Phone2)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Phone2)
#Html.ValidationMessageFor(model => model.Phone2)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AllDistricts)
</div>
<div class="editor-field">
#Html.CheckBoxFor(model => model.AllDistricts)
#Html.ValidationMessageFor(model => model.AllDistricts)
</div>
<table>
<tr>
<td>
<div class="editor-label">
#Html.LabelFor(model => model.AreaId)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.AreaId,
Model.Areas.Select(s => new SelectListItem {
Selected = s.Id == Model.AreaId,
Text = s.Name,
Value = s.Id.ToString()
}),
"Выберите район...")
#Html.ValidationMessageFor(model => model.AreaId)
</div>
</td>
<td>или</td>
<td>
<div class="editor-label">
#Html.LabelFor(model => model.DistrictId)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.DistrictId,
Model.Districts.Select(s => new SelectListItem {
Selected = s.Id == Model.DistrictId,
Text = s.Name,
Value = s.Id.ToString()
}),
"Выберите округ...")
#Html.ValidationMessageFor(model => model.DistrictId)
</div>
</td>
</tr>
</table>
</fieldset>
SchemaBuilder.CreateTable("AdRecord", table => table
.ContentPartRecord()
.Column<string>("Title")
.Column<string>("Url")
.Column<string>("Email")
.Column<string>("Phone1")
.Column<string>("Phone2")
.Column<int>("AreaRecord_Id")
.Column<int>("DistrictRecord_Id")
.Column<bool>("AllDistricts")
);
ContentDefinitionManager.AlterPartDefinition(
typeof(AdPart).Name, cfg => cfg.Attachable());
ContentDefinitionManager.AlterTypeDefinition(
"ArealAds_Ad", cfg => cfg
.WithPart("CommonPart")
.WithPart("AdPart")
.Creatable()
);
You're probably missing an entry in placement.info.
Add this into the placement.info file in your module (not the placement.info for yoru theme, since the theme is not active while you're in the dashboard):
`<Place Parts_Ad_Edit="Content:1" />`