Add Data to a model - asp.net-mvc

I have created a model with a List in it
namespace OMIv2._1KSWilson.Models
{
public class LegendClassVM
{
public List <string> legendValues { get; set; }
}
}
then i have a foreach loop that creates strings that i want to use.
List<string> values = new List<string>();
foreach (Feature f in allFeatures)
{
if (f.ColumnValues.ContainsKey(layercode))
{
if (!values.Contains(f.ColumnValues[layercode].ToString()))
{
values.Add(f.ColumnValues[layercode].ToString());
}
}
}
how would i add these items to the model list. this code executes five times so i need to store alot of data.
any suggestions would be greatly appreciated

try with this
public ActionResult Index()
{
LegendClassVM model = new LegendClassVM();
model.legendValues = new List <string>();
foreach (Feature f in allFeatures)
{
if (f.ColumnValues.ContainsKey(layercode))
{
if (!values.Contains(f.ColumnValues[layercode].ToString()))
{
model.legendValues.Add(f.ColumnValues[layercode].ToString());
}
}
}
return View(model);
}

Related

Linq2DB and query for dynamic

I'm trying to perform a query without having created a model that maps it.
Consider this snippet
public IDictionary<string, int> GetParentelaMapping()
{
using (var conn = dataContextFactory.Create())
{
var result = conn.Query<dynamic>("SELECT ID_GRADO_PARENTELA,GRADO_PARENTELA FROM GRADO_PARENTELA")
.ToDictionary(
row => (string)row.GRADO_PARENTELA,
row => (int)row.ID_GRADO_PARENTELA, StringComparer.OrdinalIgnoreCase);
return result;
}
}
It gaves me an exception that
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: ''int' does not contain a definition for 'GRADO_PARENTELA''
How can I handle such a case?
Thanks
Unfortunately this feature currently is not supported. Track new issue #1591 for that.
As a workaround i suggest to define additional class for reading such result:
class ParentelaMapping
{
public int ID_GRADO_PARENTELA { get; set; }
pulbic string GRADO_PARENTELA { get; set; }
}
public IDictionary<string, int> GetParentelaMapping()
{
using (var conn = dataContextFactory.Create())
{
var result = conn.Query<ParentelaMapping>("SELECT ID_GRADO_PARENTELA,GRADO_PARENTELA FROM GRADO_PARENTELA")
.ToDictionary(
row => row.GRADO_PARENTELA,
row => row.ID_GRADO_PARENTELA, StringComparer.OrdinalIgnoreCase);
return result;
}
}
P.S.
linq2db designed to work better with linq queries so consider to rewrite your query in the following way:
[Table("GRADO_PARENTELA")]
class GrandoParentela
{
public int ID_GRADO_PARENTELA { get; set; }
pulbic string GRADO_PARENTELA { get; set; }
}
public IDictionary<string, int> GetParentelaMapping()
{
using (var conn = dataContextFactory.Create())
{
var result = conn.GetTable<GrandoParentela>()
.ToDictionary(
row => row.GRADO_PARENTELA,
row => row.ID_GRADO_PARENTELA, StringComparer.OrdinalIgnoreCase);
return result;
}
}

Get recent inserted Id and send in to another controllers view

EDITED:
I have Created CRUD Functions for each Modals and now i am trying to get recent Inserted Id and use it in different view.
Here is what I have tried so far
I have created 2 classes(Layer based) for CRUD function for each ContextEntities db to practice pure OOP recursive approach and following is the code.
1. Access Layer
ViolatorDB
public class ViolatorDB
{
private TPCAEntities db;
public ViolatorDB()
{
db = new TPCAEntities();
}
public IEnumerable<tbl_Violator> GetALL()
{
return db.tbl_Violator.ToList();
}
public tbl_Violator GetByID(int id)
{
return db.tbl_Violator.Find(id);
}
public void Insert(tbl_Violator Violator)
{
db.tbl_Violator.Add(Violator);
Save();
}
public void Delete(int id)
{
tbl_Violator Violator = db.tbl_Violator.Find(id);
db.tbl_Violator.Remove(Violator);
Save();
}
public void Update(tbl_Violator Violator)
{
db.Entry(Violator).State = EntityState.Modified;
Save();
}
public void Save()
{
db.SaveChanges();
}
}
2. Logic Layer
ViolatorBs
public class ViolatorBs
{
private ViolatorDB objDb;
public ViolatorBs()
{
objDb = new ViolatorDB();
}
public IEnumerable<tbl_Violator> GetALL()
{
return objDb.GetALL();
}
public tbl_Violator GetByID(int id)
{
return objDb.GetByID(id);
}
public void Insert(tbl_Violator Violator)
{
objDb.Insert(Violator);
}
public void Delete(int id)
{
objDb.Delete(id);
}
public void Update(tbl_Violator Vioaltor)
{
objDb.Update(Vioaltor);
}
}
And Finally using Logic Layer functions in presentation Layer.Here insertion is performed as:
public class CreateViolatorController : Controller
{
public TPCAEntities db = new TPCAEntities();
private ViolatorBs objBs;
public CreateViolatorController()
{
objBs = new ViolatorBs();
}
public ActionResult Index()
{
var voilator = new tbl_Violator();
voilator=db.tbl_Violator.Add(voilator);
ViewBag.id = voilator.VID;
return View();
}
[HttpPost]
public ActionResult Create(tbl_Violator Violator)
{
try
{
if (ModelState.IsValid)
{
objBs.Insert(Violator);
TempData["Msg"] = "Violator Created successfully";
return RedirectToAction("Index");
}
else
{
return View("Index");
}
}
catch (Exception ex)
{
TempData["Msg"] = "Failed..." + ex.Message + " " + ex.ToString();
return RedirectToAction("Index");
}
}
}
Now here is the main part how do i get perticuller inserted id in another controller named Dues while performing insertion ?
In sqlqery I would have used ##IDENTITY but in Entity Framework I'm not sure.
I'm new to mvc framework any suggestion or help is appreciated Thanks in Advance.
Once you save your db context the id is populated back to your entity by EF automatically.
for example.
using(var context = new DbContext())
{
var employee = new Employee(); //this has an id property
context.Employees.Add(employee);
context.SaveChanges();
var id = employee.id; // you will find the id here populated by EF
}
You dont need to add and save your table as you have done this already in your voilatorDB class just fetch the last id like following
var id = yourTableName.Id;
db.yourTableName.find(id);
Or you can simply write one line code to achive that using VoilatorBs class function
GetbyID(id);

How to find which of the items are modified in a list when we work on client side and send it to server side in Asp.net MVC

I am working on SOA based project and i got got a situation where I am sending the whole array of object to server and then I have to see which of the objects are new and which one I have to update, hence I am looking for some generic function which can get me the list with update , delete or insert attribute
I was facing the same problem where I was sending entity with multiple children entities. The challenge was to figure out what child entity has been updated, added or deleted. Here what I did.
Implemented IObjectWithState with ChildEntity. (Inspired from one of pluralsight entityframework video)
Pull the server side version of entity.
Invoked FindDifference to get the difference of Child entities on client and server
IList<ClassTicket> clientSideTickets = /// What received from client
IList<ClassTicket> serverSideTickets = /// What received from database
var diffTickets = FindDifference(clientSideTickets ,serverSideTickets ,
(ticket1, ticket2) => ticket1.Id == ticket2.Id,(ticket1, ticket2) => ticket1.Name == ticket2.Name && ticket1.NoOfTicketsAvailable == ticket2.NoOfTicketsAvailable && ticket1.Price == ticket2.Price);
public interface IObjectWithState
{
State State { get; set; }
}
// My Child Entity
public class ClassTicket: IObjectWithState
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public short NoOfTicketsAvailable { get; set; }
public State State { get; set; }
}
public static IEnumerable<T> FindDifference<T>(IEnumerable<T> clientList, IEnumerable<T> serverList, Func<T, T, bool> identityDetector, Func<T, T, bool> changeDetector) where T : IObjectWithState
{
var finalList = new List<T>();
var clientItems = clientList as T[] ?? clientList.ToArray();
var serverItems = serverList as T[] ?? serverList.ToArray();
foreach (var clientItem in clientItems)
{
bool foundInServerList = false;
foreach (var serverItem in serverItems)
{
if(identityDetector(clientItem, serverItem))
{
foundInServerList = true;
clientItem.State = !changeDetector(clientItem, serverItem) ? State.Modified : State.Unchanged;
finalList.Add(clientItem);
break;
}
}
if(!foundInServerList)
{
clientItem.State = State.Added;
finalList.Add(clientItem);
}
}
foreach (var serverItem in serverItems)
{
var foundInClientList = clientItems.Any(clientItem => identityDetector(serverItem, clientItem));
if (!foundInClientList)
{
serverItem.State = State.Deleted;
finalList.Add(serverItem);
}
}
return finalList;
}

Loop through fields of two single objects entities

[HttpPost]
public ActionResult Edit(orders neworders)
{
string modifields;
orders oldorders = HDB.orders.Where(c => c.id_order == cmd.id_order).First();
foreach (var field in oldorders)
{
if(field!= neworders.samefield)
{
modifields+=nameoffield ;
}
}
}
Q How can i compare a field from the new and from the old record and save the name of the field if the value is changed?
First() returns a single object, so can't be iterated over.
Reading between the lines it looks like you want to iterate over all the fields on the object. In that case you can use reflection to return a list of fields which you can then iterate over.
foreach (var field in oldorders.GetType().GetFields())
{
var value = field.GetValue(oldorders);
}
EDIT: from your other comments it looks like you are wanting to compare the object against another object, in which case you are better off implementing the IEquatable<T> interface. E.g.
class Order : IEquatable<Order>
{
// TODO: add properties of an Order
public string foo { get; set; }
public string bar { get; set; }
public bool Equals(Order other)
{
foreach (var field in typeof(Order).GetFields())
{
if (field.GetValue(this) != field.GetValue(other))
{
return false;
}
}
foreach (var property in typeof(Order).GetProperties())
{
if (property.GetValue(this, null) != property.GetValue(other, null))
{
return false;
}
}
return true;
}
}
An example of the Equals() method override to compare instances of the same class
public override bool Equals(object anObject)
{
if (anObject is Order)
{
Order newOrder = (Order)anObject;
if (newOrder.Name.Equals(this.Name)) //add additional comparisons as needed. You could also use a foreach loop here as Tony shows below
{
return true;
}
foreach (var field in typeof(Order).GetFields())
{
if (field.GetValue(this) != field.GetValue(newOrder)) { return false; }
}
foreach (var property in typeof(Order).GetProperties())
{
if (property.GetValue(this, null) != property.GetValue(newOrder, null)) { return false; }
}
}
return false;
}
Here's how to call in your action:
[HttpPost] public ActionResult Edit(orders neworder)
{
orders oldorder = HDB.orders.Where(c => c.id_order == cmd.id_order).First();
if(oldorder.Equals(newOrder)
{
//do wome work
}
}
I would say your orders class doesn't implement the IEnumerable interface properly. In order to use foreach in this manner you must implement the interface and at least account for all of the methods required to support it.
http://msdn.microsoft.com/en-us/library/9eekhta0.aspx
Your oldrders variable is not Enumerable. The First() method returns a sinlge object. Remove the .First() and you will have an Enumerable object which the foreach loop can use

Entity Framework 4 w/ MVC 2 - fighting against EF4's inability to allow empty strings in form fields

FINAL EDIT: Success! There's a data annotation rule that stops empty strings from being set to null. I was able to use the solution here (Server-side validation of a REQUIRED String Property in MVC2 Entity Framework 4 does not work). Works like a charm now. I'll keep the rest of my post as-is in case anyone can learn from it.
Decided to rewrite this post to give all the detail I can. Long post, given all the code, so please bear with me.
I'm writing an MVC 2 project using EF4 as a base. All of my db columns are non-nullable.
Like I said before, I'm having issues with EF4 throwing a ConstraintException when I test the case of an empty form. The exception is springing up from the Designer.cs file, specifically in code like:
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
[DataMemberAttribute()]
public global::System.String GameTitle
{
get
{
return _GameTitle;
}
set
{
OnGameTitleChanging(value);
ReportPropertyChanging("GameTitle");
_GameTitle = StructuralObject.SetValidValue(value, false); // <-- this is where the exception is being thrown
ReportPropertyChanged("GameTitle");
OnGameTitleChanged();
}
}
private global::System.String _GameTitle;
partial void OnGameTitleChanging(global::System.String value);
partial void OnGameTitleChanged();
The exception IS NOT being caught and handled by MVC. Instead, I keep getting an uncaught exception and a YSoD. My controller (excuse the mess - I was trying to get repository level validation to work, see below):
[HttpPost]
public ActionResult CreateReview([Bind(Prefix = "GameData")]Game newGame, int[] PlatformIDs)
{
/* try
{
_gameRepository.ValidateGame(newGame, PlatformIDs);
}
catch (RulesException ex)
{
ex.CopyTo(ModelState);
}
if (ModelState.IsValid)
{
return RedirectToAction("Index");
}
else
{
var genres = _siteDB.Genres.OrderBy(g => g.Name).ToList();
var platforms = _siteDB.Platforms.OrderBy(p => p.PlatformID).ToList();
List<PlatformListing> platformListings = new List<PlatformListing>();
foreach(Platform platform in platforms)
{
platformListings.Add(new PlatformListing { Platform = platform, IsSelected = false });
}
var model = new AdminGameViewModel { GameData = newGame, AllGenres = genres, AllPlatforms = platformListings };
return View(model);
}*/
if (PlatformIDs == null || PlatformIDs.Length == 0)
{
ModelState.AddModelError("PlatformIDs", "You need to select at least one platform for the game");
}
try
{
foreach(var p in PlatformIDs)
{
Platform plat = _siteDB.Platforms.Single(pl => p == pl.PlatformID);
newGame.Platforms.Add(plat);
}
newGame.LastModified = DateTime.Now;
if (ModelState.IsValid)
{
_siteDB.Games.AddObject(newGame);
_siteDB.SaveChanges();
return RedirectToAction("Index");
}
else
{
return View();
}
}
catch
{
return View();
}
}
I've tried several things to get validation to work. The first was Steven Sanderson's "Let the model handle it" as described in his aPress MVC2 book. I figured the best place to attempt validation would be in the repository, since the data would have to be passed in there anyway, and I'd like to keep my controller thin. The repo:
public class HGGameRepository : IGameRepository
{
private HGEntities _siteDB = new HGEntities();
public List<Game> Games
{
get { return _siteDB.Games.ToList(); }
}
public void ValidateGame(Game game, int[] PlatformIDs)
{
var errors = new RulesException<Game>();
if (string.IsNullOrEmpty(game.GameTitle))
{
errors.ErrorFor(x => x.GameTitle, "A game must have a title");
}
if (string.IsNullOrEmpty(game.ReviewText))
{
errors.ErrorFor(x => x.ReviewText, "A review must be written");
}
if (game.ReviewScore <= 0 || game.ReviewScore > 5)
{
errors.ErrorFor(x => x.ReviewScore, "A game must have a review score, and the score must be between 1 and 5");
}
if (string.IsNullOrEmpty(game.Pros))
{
errors.ErrorFor(x => x.Pros, "Each game review must have a list of pros");
}
if (string.IsNullOrEmpty(game.Cons))
{
errors.ErrorFor(x => x.Cons, "Each game review must have a list of cons");
}
if (PlatformIDs == null || PlatformIDs.Length == 0)
{
errors.ErrorForModel("A game must belong to at least one platform");
}
if (game.Genre.Equals(null) || game.GenreID == 0)
{
errors.ErrorFor(x => x.Genre, "A game must be associated with a genre");
}
if (errors.Errors.Any())
{
throw errors;
}
else
{
game.Platforms.Clear(); // see if there's a more elegant way to remove changed platforms
foreach (int id in PlatformIDs)
{
Platform plat = _siteDB.Platforms.Single(pl => pl.PlatformID == id);
game.Platforms.Add(plat);
}
SaveGame(game);
}
}
public void SaveGame(Game game)
{
if (game.GameID == 0)
{
_siteDB.Games.AddObject(game);
}
game.LastModified = DateTime.Now;
_siteDB.SaveChanges();
}
public Game GetGame(int id)
{
return _siteDB.Games.Include("Genre").Include("Platforms").SingleOrDefault(g => g.GameID == id);
}
public IEnumerable<Game> GetGame(string title)
{
return _siteDB.Games.Include("Genre").Include("Platforms").Where(g => g.GameTitle.StartsWith(title)).AsEnumerable<Game>();
}
public List<Game> GetGamesByGenre(int id)
{
return _siteDB.Games.Where(g => g.GenreID == id).ToList();
}
public List<Game> GetGamesByGenre(string genre)
{
return _siteDB.Games.Where(g => g.Genre.Name == genre).ToList();
}
public List<Game> GetGamesByPlatform(int id)
{
return _siteDB.Games.Where(g => g.Platforms.Any(p => p.PlatformID == id)).ToList();
}
public List<Game> GetGamesByPlatform(string platform)
{
return _siteDB.Games.Where(g => g.Platforms.Any(p => p.Name == platform)).ToList();
}
}
}
The RulesException/Rule Violation classes (as taken from his book):
public class RuleViolation
{
public LambdaExpression Property { get; set; }
public string Message { get; set; }
}
public class RulesException : Exception
{
public readonly IList<RuleViolation> Errors = new List<RuleViolation>();
private readonly static Expression<Func<object, object>> thisObject = x => x;
public void ErrorForModel(string message)
{
Errors.Add(new RuleViolation { Property = thisObject, Message = message });
}
}
public class RulesException<TModel> : RulesException
{
public void ErrorFor<TProperty>(Expression<Func<TModel, TProperty>> property, string message)
{
Errors.Add(new RuleViolation { Property = property, Message = message });
}
}
That did not work, so I decided to try Chris Sells' method of using IDataErrorInfo (as seen here: http://sellsbrothers.com/Posts/Details/12700). My code:
public partial class Game : IDataErrorInfo
{
public string Error
{
get
{
if (Platforms.Count == 0)
{
return "A game must be associated with at least one platform";
}
return null;
}
}
public string this[string columnName]
{
get
{
switch (columnName)
{
case "GameTitle":
if (string.IsNullOrEmpty(GameTitle))
{
return "Game must have a title";
}
break;
case "ReviewText":
if (string.IsNullOrEmpty(ReviewText))
{
return "Game must have an associated review";
}
break;
case "Pros":
if (string.IsNullOrEmpty(Pros))
{
return "Game must have a list of pros";
}
break;
case "Cons":
if (string.IsNullOrEmpty(Cons))
{
return "Game must have a list of cons";
}
break;
}
return null;
}
}
}
}
Again, it did not work.
Trying simple data annotations:
[MetadataType(typeof(GameValidation))]
public partial class Game
{
class GameValidation
{
[Required(ErrorMessage="A game must have a title")]
public string GameTitle { get; set; }
[Required(ErrorMessage = "A game must have an associated review")]
public string ReviewText { get; set; }
[Required(ErrorMessage="A game must have a list of pros associated with it")]
public string Pros { get; set; }
[Required(ErrorMessage="A game must have a set of cons associated with it")]
public string Cons { get; set; }
}
}
Also did not work.
The common denominator with all of this is the EF designer throwing an exception, and the exception not being caught by MVC. I'm at a complete loss.
EDIT: Cross-posted from here: http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/643e0267-fc7c-44c4-99da-ced643a736bf
Same issue with someone else: http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/4fee653a-4c8c-4a40-b3cf-4944923a8c8d/
Personally i don't see a point in storing this in the database:
Id Description
1 Foo
2 ''
3 Bar
Seems silly to me.
Instead of storing blank fields you make it nullable.
If you disagree, then you could set a default value in the database, and set the StoreGeneratedPattern to Computed.
Or you could have a ctor for the entity, which sets the value.

Resources