Saving Changes using breeze without Entity Framework - breeze

I am beginner in breeze, I want to integrate it into an ASP.net MVC4 project .
I have the same problem in Saving Data Using Breeze.js
but this post did not answer the problem and I hope we can do it this time
The problem is that I don’t have to use Entity Framework and I don’t know how to replace ContextProvider in SaveChanges method in the controller
[HttpPost]
public SaveResult SaveChanges (JObject saveBundle) {
return ContextProvider.SaveChanges (saveBundle);
}
I also tried to customize ressourceName by using SaveOptions:
var option = new breeze.SaveOptions ({resourceName 'MyContoller'});
entityManager.saveChanges (null, optional)
. then (
alert ("ok");
)
. fail (function (e) {
alert (e);
});
When I run it no problem starts but the controller does not receive data!
So my question is:
How can I save changes with breeze without using EntityFramework?
Thank you in advance

To solve this problem I redefined savaChanges method to read the json data and assign it to my object, but I'm not sure that it is the right way:
This is my SaveChanges method
[HttpPost]
public void SaveChanges(JObject saveBundle)
{
JToken jMyObject = saveBundle["entities"];
MyClass myObject= new MyClass ();
string state=(string) jMyObject [0]["entityAspect"]["entityState"];
if (state == "Added")
{
myObject.name =
(string) jMyObject [0]["name"];
CreateEntity(myObject);
}
}

Related

breezejs cancel saveChanges due to validation failure in BeforeSaveEntity

I created my own ContextProvider, sub classed from EFContextProvider. In BeforeSaveEntity I am running some business logic to validate the transaction. I need the updates to be "all or nothing", so if the 3rd entity in the collection fails the validation, the entire batch should be discarded, even though Ive already returned "true" for the first 2 entities.
I have a class level property thats getting set when any entity fails. In the final check in BeforeSaveEntities I can get the value of the flag.
I think this is where I can abort the update, but not sure how. Do I clear the map? Or throw an error?
Also, I will need to re-query the DB for my validation routines. I've read some posts that talk about creating a 2nd instance of the context to do the querying for the current values. Is there some docs on doing this, or gotchas I need to be aware of?
thanks
In your BeforeSaveEntities call you can throw an EntityErrorsException: Here is an example where we throw an exception if there is attempt to save any "Order" objects within a save bundle:
[HttpPost]
public SaveResult SaveWithEntityErrorsException(JObject saveBundle) {
ContextProvider.BeforeSaveEntitiesDelegate = ThrowEntityErrorsException;
return ContextProvider.SaveChanges(saveBundle);
}
private Dictionary<Type, List<EntityInfo>> ThrowEntityErrorsException(Dictionary<Type, List<EntityInfo>> saveMap) {
List<EntityInfo> orderInfos;
if (saveMap.TryGetValue(typeof(Order), out orderInfos)) {
var errors = orderInfos.Select(oi => {
return new EntityError() {
EntityTypeName = typeof(Order).FullName,
ErrorMessage = "Cannot save orders with this save method",
ErrorName = "WrongMethod",
KeyValues = new object[] { ((Order) oi.Entity).OrderID },
PropertyName = "OrderID"
};
return new EFEntityError(oi, "WrongMethod", "Cannot save orders with this save method", "OrderID");
});
var ex = new EntityErrorsException("test of custom exception message", errors);
// if you want to see a different error status code use this.
// ex.StatusCode = HttpStatusCode.Conflict; // Conflict = 409 ; default is Forbidden (403).
throw ex;
}
return saveMap;
}
And you should use BeforeSaveEntities exclusively instead of BeforeSaveEntity as your save logic becomes more complicated.
I had a requirement to perform server side calculations on entities that had been changed on the client - without saving - and get the results back to the client. The solution based on Breeze named saves that I came up with could be useful in this situation too.
I added the following method to the base class for my Breeze controllers.
protected SaveResult OverrideSaveChanges(JObject saveBundle, Action<List<object>> action, bool shouldSave = false)
{
var saveChangesDelegate = new SaveChangesOverride(action, shouldSave);
return saveChangesDelegate.Execute(saveBundle, ContextProvider);
This allows concrete controllers to implement named saves very simply. The saveBundle plus an Action<List<object>> are passed into the OverrideSaveChanges method. The action can make whatever modifications to the entities that are required and those changes will be propagated back to the client. The objects in the list are the entities that the client recognized as having changes and sent down to the server for the named save. Optionally, you could pass a shouldSave argument with a value of true to have the entities saved - the default is false.
OverrideChanges delegates to SaveChangesOverride for most of the heavy lifting.
public class SaveChangesOverride
{
public SaveChangesOverride(Action<List<object>> action, bool shouldSave = false)
{
Action = action;
ShouldSave = shouldSave;
}
private readonly Action<List<object>> Action;
private readonly bool ShouldSave;
public List<object> Entities;
public SaveResult Execute(JObject saveBundle, ContextProvider contextProvider)
{
contextProvider.BeforeSaveEntitiesDelegate = OnBeforeSaveEntities;
contextProvider.SaveChanges(saveBundle);
return new SaveResult
{
Entities = Entities,
KeyMappings = new List<KeyMapping>()
};
}
private Dictionary<Type, List<EntityInfo>> OnBeforeSaveEntities(Dictionary<Type, List<EntityInfo>> arg)
{
Entities = arg.SelectMany(x => x.Value).Select(x => x.Entity).ToList();
Action(Entities);
if (!ShouldSave)
{
return new Dictionary<Type, List<EntityInfo>>();
}
return arg;
}
}
Although we have access to all of the changed entities in the saveBundle actually performing the modifications in OnBeforeSaveChanges allows us to work with entities rather than a JObject.
Also, contextProvider.SaveChanges must be called regardless of whether we wish to have the entities saved. This is what triggers OnBeforeSaveEntities to be called. To ensure that the entities are not saved despite calling SaveChanges (if that is what is desired), rather than returning arg from OnBeforeSaveEntities, an empty dictionary is returned.
To ensure that the changes make it back to the client, a reference to the entities is saved in OnBeforeSaveEntities. This is used in Execute to prepare a SaveResult that is populated with the modified entities.

Server side Validations and security in breeze.js

I’m trying save some entities using breeze.js. Breeze is working fine and it saves all the changes as required. However, I have trouble validating and ensuring authorization is the server side. From what I’ve gather so far I guess the only way to do this is via examining the JObject passed into save bundles and constructing corresponding objects on the server side. I have to do this (instead of relying Breeze.SaveChanges as I have some logic on the server side). How do I do this? And how do I construct the Breeze.WebApi. SaveResult?
Idea of any other way of solving this problem is also very welcome 
This should be done by implementing a custom EFContextProvider.
The code below implements a custom EFContextProvider for the Northwind database and was taken directly from the documentation on the breeze.com website .
public class NorthwindContextProvider: EFContextProvider<NorthwindIBContext> {
public NorthwindContextProvider() : base() { }
protected override bool BeforeSaveEntity(EntityInfo entityInfo) {
// return false if we don’t want the entity saved.
// prohibit any additions of entities of type 'Role'
if (entityInfo.Entity.GetType() == typeof(Role)
&& entityInfo.EntityState == EntityState.Added) {
return false;
} else {
return true;
}
}
protected override Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap) {
// return a map of those entities we want saved.
return saveMap;
}
}
#jaq316 is correct: a custom EFContextProvider is the place to intercept changes coming from the client. It is the place to both authorize and validate them . The documentation has more details. The essence of it is that you scrutinize the proposed changes within your overrides of the BeforeSaveEntity and BeforeSaveEntities virtual methods; alternatively you can attach handlers to the BeforeSaveEntityDelegate and BeforeSaveEntitiesDelegate.
So here is my thought on this one, since I am not using a ContextProvider at all. I am utilizing a SQL back-end and Ninject to inject a repository dependency into each controller I have. I have more items than the demo for "Todos" and want separate controllers out there and repositories as well. If I created the ContextProvider as shown by the breeze docs I would have one ContextProvider file with all the entities in it. This would be huge. If I separated them into separate contexts I would duplicating code in all the overrides.
Here is my Save Changes method in ContactFormController.cs :
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
var sr = new SaveResult() { KeyMappings = new List<KeyMapping>(), Entities = new List<object>()};
dynamic entity = saveBundle["entities"][0];
ContactForm form = entity.ToObject<ContactForm>();
EntityState state = entity.entityAspect.entityState;
switch (state)
{
case EntityState.Added:
KeyMapping mapping = new KeyMapping(){EntityTypeName = typeof(ContactForm).ToString(), TempValue = form.Id };
var validationErrors = _contactFormService.ProcessContactForm(ref form).Cast<object>().ToList();
//if we succeed then update the mappings
if (validationErrors.Count == 0)
{
//setup the new mappings
mapping.RealValue = form.Id;
sr.KeyMappings.Add(mapping);
//link the entity
sr.Entities.Add(form);
}
else
{
sr.Errors = validationErrors;
}
break;
}
return sr;
}
I dynamically change the endpoints before saves on the client side so that each controller in my webapi has a SaveChanges() method. I then call into the appropriate repository to process the backend functions as needed. This way I can run mock code or actual SQL changes depending on the repo injected.
If their are errors on the Processing of the form then we cast our custom List list to a List and assign it to the Errors property of the SaveResult. If there are no errors we send back the new key mappings to be updated on the client.
Ideally I want to reduce all the code in this controller and perhaps abstract it out to a utility method so there is less repeat in every controller. I like this method because then I can create normal repositories and not have them depend on a ContextProvider. Breeze independent at that point.

Best way to transfer an Entity Framework object over the web and back via JSON

I've got some MVC code that serializes an EF 3.5 object into an anonymous type for return as a JSON result to an AJAX call on my page. The hurdle I have is that when I send the object back to the server via JSON, (and let the ModelBinder deserialize it for me into my EF type), I have to update it in my Entity Framework context manually. Or at least that's what I'm doing now. It has no EntityKey, so attaching it fails. I end up having to look up the old object and update it property by property. Any ideas around this? Is the solution to pass the EntityKey around with my object?
Here's what I have:
public void Update(Album album)
{
using (var db = new BandSitesMasterEntities())
{
var albumToUpdate = db.Album.First(x => x.ID == album.ID);
albumToUpdate.AlbumTitle = album.AlbumTitle;
albumToUpdate.Description = album.Description;
albumToUpdate.ReleaseYear = album.ReleaseYear;
albumToUpdate.ImageURL = album.ImageURL;
albumToUpdate.OtherURL = album.OtherURL;
db.SaveChanges();
}
}
And here's what I'd like to do, or something similar:
public void Update(Album album)
{
using (var db = new BandSitesMasterEntities())
{
db.Attach(album)
db.SaveChanges();
}
}
or you could use AutoMapper to map those fields for you, so you'd just add one extra line to your example.
Why not just use the UpdateModel or TryUpdateModel controller methods instead? It works really well with EF and you can even explicitly set the included property list.
The id parameter will auto-map via the MVC framework to the hidden field on your form specifying the id.
public void Update(int id, FormCollection collection)
{
using (var db = new BandSitesMasterEntities())
{
var albumToUpdate = db.Album.First(x => x.ID == id);
//use UpdateModel to update object, or even TryUpdateModel
UpdateModel(albumToUpdate, new string[] { "AlbumTitle", "Description", "ReleaseYear", "ImageURL", "OtherURL" });
db.SaveChanges();
}
}
This became much easier for us in EF 4.0. This is what we did in EF 3.5:
public static void AttachAsModified(this ObjectContext objectContext, string setName, object entity,
IEnumerable<String> modifiedFields)
{
objectContext.AttachTo(setName, entity);
ObjectStateEntry stateEntry = objectContext.ObjectStateManager.GetObjectStateEntry(entity);
foreach (String field in modifiedFields)
{
stateEntry.SetModifiedProperty(field);
}
}
And then:
using (var db = new BandSitesMasterEntities())
{
db.AttachAsModified("Album", album, new string[] { "AlbumTitle", "Description", "ReleaseYear", "ImageURL", "OtherURL" })
db.SaveChanges();
}
It becomes more complicated if you have foreign key constraints, but it looks like you don't.
There is no way around the entity key issue. You either have to add it to your anonymous type or I would recommend you port your code to using data services.
http://www.hanselman.com/blog/jQueryToShipWithASPNETMVCAndVisualStudio.aspx
which would allow you to do all of the db manipulation on the client side.
http://msdn.microsoft.com/en-us/data/bb931106.aspx
Did you try something like:
object original;
var key = contexte..CreateEntityKey("EntitySet", modified);
if(contexte.TryGetObjectByKey(key, out original))
{
var originalEntity = (YourEntityType)original;
// You have to mannualy set your entityKey
originalEntity.YourEntityReference.EntityKey = new EntityKey("Entities.EntitySet", "Id", modified.YourEntity.Id);
contexte.ApplyPropertyChanges("EntitySet", modified);
}
contexte.SaveChanges();
Assuming that your EntityReference are set by dropDown, you'll still have the Id
In your Album entity's partial class you may define a CopyFrom function and call it from your Update function
partial class Album
{
public void CopyFrom(Album album)
{
//individual field copying here
}
}
public void Update(Album album)
{
...
albumToUpdate.CopyFrom(album);
...
}

Iterating over an unknown IQueryable's properties?

Forgive me if this has been asked before; I couldn't find anything close after a few searches:
I'm trying to write an ActionFilter in MVC that will "intercept" an IQueryable and nullify all the parent-child relationships at runtime. I'm doing this because Linq does not serialize objects properly if they have parent-child relationships (it throws a circular reference error because the parent refers to the child, which refers back to the parent and so on), and I need the object serialized to Json for an Ajax call. I have tried marking the child relationship in the DBML file with a privacy status of internal, and while this fixes the serialization problem, it also hides the child members from the view engine when the page renders, causing another error to be thrown. So, by fixing one problem, I cause another.
The only thing that fixes both problems is to manually set the child members to null just before returning the serialization, but I'm trying to avoid doing that because it's cumbersome, not reusable, etc. I'd rather use an ActionFilter to inspect the IQueryable that is being serialized and nullify any members with a Type of EntitySet (how Foreign Keys/Associations are represented). However, I don't have much experience with Reflection and can't find any examples that illustrate how to do something like this. So... is this possible with Reflection? Is there a better way to accomplish the same thing? I'll post the relevant code tomorrow when I'm back at my work computer.
Thanks,
Daniel
As promised, the code:
[GridAction]
public ActionResult _GetGrid()
{
IQueryable<Form> result = formRepository.GetAll();
foreach (Form f in result)
{
f.LineItems = null;
f.Notes = null;
}
return View(new GridModel<Form> { Data = result });
}
An added wrinkle is that I'm using the new Telerik MVC Extensions, so I'm not actually serializing the Json myself -- I'm just returning the IQueryable in an IGridModel, and the action filter [GridAction] does the rest.
So, just in case anyone's curious, here's how I finally solved this problem: I modified Damien Guard's T4 template to include the attribute [ScriptIgnore] above entities of type Association. This lets the JSON serializer know to not bother serializing these, thus preventing the circular reference problem I was getting. The generated code ends up looking like this:
private EntitySet<LineItem> _LineItems;
[ScriptIgnore]
[Association(Name=#"Form_LineItem", Storage=#"_LineItems", ThisKey=#"Id", OtherKey=#"FormId")]
public EntitySet<LineItem> LineItems
{
get {
return _LineItems;
}
set {
_LineItems.Assign(value);
}
}
This fixes the serialization problem I was having without disabling the use of child tables through LINQ. The grid action on the controller ends up looking like this:
[GridAction]
public ActionResult _GetGrid()
{
return View(new GridModel<Form> { Data = formRepository.GetAll() });
}
There are two options, one is to ignore those properties during serialization using [XmlIgnore]. The other one is to nullify the properties using reflection.
Ignore in serialization, simple usage sample that shows how to use default value in serialization:
[Serializable]
public class MyClass
{
[XmlIgnore]
public int IgnoredVal { get; set; }
public int Val { get; set; }
}
public void UsageSample()
{
var xmlSerializer = new XmlSerializer(typeof(MyClass));
var memoryStream = new MemoryStream();
var toSerialize = new MyClass { IgnoredVal = 1, Val = 2 };
xmlSerializer.Serialize(memoryStream, toSerialize);
memoryStream.Position = 0;
var deserialize = (MyClass)xmlSerializer.Deserialize(memoryStream);
Assert.AreEqual(0, deserialize.IgnoredVal);
Assert.AreEqual(2, deserialize.Val);
}
Nullify with reflection, code sample:
public void NullifyEntitySetProperties(object obj)
{
var entitySetProperties = obj.GetType().GetProperties()
.Where(property => property.PropertyType == typeof(EntitySet));
foreach (var property in entitySetProperties)
{
property.SetValue(obj, null, null);
}
}
In my opinion, if the first option can be done used in your code it's better. This option is more direct and economic.

ASP.NET MVC, LINQ and ModelBinders

Is there a pre-built ModelBinder I can use with LINQ to get an object from a DataContext and update it on a HTTP post?
For example, currently I have this block of code:
[AcceptVerbs (HttpVerbs.Post)]
public ActionResult Edit (Project project)
{
var projectService = Factory.GetService<IProjectService> ();
project = projectService.GetProject (project.ProjectId);
UpdateModel<Project> (project);
if (!ModelState.IsValid)
return View (project);
project = projectService.SaveProject (project);
return RedirectToAction ("Details", new { id = project.ProjectId });
}
(IProjectService wraps up calls to a LINQ data context)
In order to actually perform the update to the database via the LINQ data context, I need to get the project instance again and then update that instance.
Any attempt to simply save the project instance without first getting it from the data context results in nothing being written back to the database - I'm assuming because the LINQ data context knows nothing of the object it doesn't do anything with it.
Using the Attach method on the Projects table class doesn't work either btw, it throws an exception.
You should look at the implementation in Mike Hadlow's (new BSD) SutekiShop.
In there you will find a DataBindAttribute and BindUsingAttribute which, if I understand correctly, do exactly what you want to do. Notice how the DataBindAttribute.Fetch property is used to rebind the incoming data, or not, (from an HttpPost) to a LINQ entity.
I followed this pattern for one of my projects using ASP.NET MVC and LINQ-To-SQL. It works beautifully.
Here's the source: http://www.google.com/codesearch?hl=en&lr=&q=DataBind+package%3Ahttp%3A%2F%2Fsutekishop.googlecode.com&sbtn=Search
I think the project you pass in to the method is the one you want to perform UpdateModel with isn't it?
Otherwise you are trying to update with pre-existing values not new ones.
Just a thought,
Dan
Code cut out below
[AcceptVerbs (HttpVerbs.Post)]
public ActionResult Edit (Project project)
UpdateModel<Project> (project);
if (!ModelState.IsValid)
return View (project);
var projectService = Factory.GetService<IProjectService> ();
project = projectService.SaveProject (project);
return RedirectToAction ("Details", new { id = project.ProjectId });
}
You need to retrieve the original project as you do then to update it with the properties that have changed in project to update then to submit the update request.
EDIT
Try this code I found:
public static void CloneProperties(this object origin, ref object destination)
{
if (destination == null) throw new ArgumentNullException("destination", "Destination object must first be instantiated.");
foreach (var destinationProperty in destination.GetType().GetProperties())
{
if (origin != null && destinationProperty.CanWrite)
{
origin.GetType().GetProperties().Where(x => x.CanRead && (x.Name == destinationProperty.Name && x.PropertyType == destinationProperty.PropertyType)) .ToList() .ForEach(x => destinationProperty.SetValue(destination, x.GetValue(origin, null), null));
}
}
}

Resources