We are developing a single page app using ASP.NET MVC4 with Web Api + Ko + Breeze using EF Code First.
Our (simplified) data model looks like this
class Product {
public String Name { get; set; }
public ICollection<ImageCollection> ImageSets { get; set;}
public Image DefaultImage { get; set; }
}
class ImageCollection {
public ICollection<Image> Images { get; set; }
}
class Image {
public String ImageUrl { get; set; }
}
DefaultImage is a navigation property (with foreign key) and is one of the images in the ImageSets.
We are exposing a Web API method of Products() and with default Breeze configuration. JSON serialized output on the wire has references for objects (i.e., PreserveReferencesHandling.Object) so when I want to bind the ImageUrl ko is unable to resolve the value.
Html looks like this
<img data-bind="attr: { src: DefaultImage().ImageUrl, title: Name}" />
When I switch the serializer to do PreserveReferencesHandling.None, the binding works.
Question: how do I make the default config to work? or if I switch to PreserveReferencesHandling.None for Breeze what are the gotchas/downsides?
Thanks!
In general, you do NOT want to switch PreserveReferencesHandling to None because you will lose the ability to serialize circular references and your payloads will get much larger.
I don't actually understand why your binding would begin to work after setting this. The first step to understanding this is probably to check that the ko objects actually contain the correct data after your query.
Remember that breeze navigation properties are lazy-loaded, so you may not have loaded them with your initial query. Take a look at the "EntityAspect.loadNavigationProperty" method.
Related
I have a need to store an unknown data structure in a SQL Server database table field via ORMLite. This is to support a timeline feature on a website where each step on the timeline contains different information, and I want to store them as generic "Steps", with the variable data in a "StepData" property. I have the POCO set up like this:
public class ItemStep
{
public ItemStep()
{
this.Complete = false;
}
[Alias("ItemStepId")]
public Guid Id { get; set; }
[References(typeof(Item))]
public Guid ItemId { get; set; }
[References(typeof(Step))]
public int StepId { get; set; }
public object StepData { get; set; }
[Reference]
public Step Step { get; set; }
public bool Complete { get; set; }
public DateTime? CompletedOn { get; set; }
}
My front-end send a JSON object for StepData, and it's saved to the database appropriately.
{itemAmount:1000,isRed:False,isBlue:True,conversion:True}
Now, when I go to retrieve that data using...
List<ItemStep> itemSteps = Db.Select<ItemStep>(q => q.ItemId == request.ItemId).OrderByDescending(q => q.StepId).ToList<ItemStep>();
...the "StepData" node of the JSON response on the client is not a Javascript Array object as I'm expecting. So, on the client (AngularJS app using Coffeescript),
ItemStep.getItemSteps(ItemId).then((response) ->
$scope.StepData = response.data.itemSteps[0].stepData
is a double-quoted string of the JSON array.
"{itemAmount:1000,isRed:False,isBlue:True,conversion:True}"
Can anybody help me with this? I've tried parsing that string as JSON and I can't seem to get it to work:
JSON.parse($scope.StepData)
I'm using the exact same methodology in other areas of the app to store and retrieve things like addresses, with the only difference I can see being that there is a specified Address class.
Thanks!
Found this link that solved my problem: https://github.com/ServiceStackV3/mythz_blog/blob/master/pages/314.md
Essentially I added a "Type" field to the ItemStep class, and set that when I create a new row (create the next step in the timeline). Then, when I retrieve that record, I call a method like "GetBody" in the referenced link (GetStepData for me), that deserializes the object using the stored Type. I then stuff that back into a generic "object" type in the return POCO so that I can include many steps of varying types in the same call. Works great!
Thanks Mythz for the blog post!
Following is the Observable collection which is available in the viewmodel:
ObservableCollection<Category> productcat;
further split of Category class is as follows:
public class Category
{
public string CategoryName { get; set;}
public List<ProductData> Products
{
get;
set;
}
}
ProductData class as follows:
public class ProductData
{
public string ProductImageUri { get; set;}
public string ProductTitle { get; set;}
public float productcost { get; set;}
}
Part 1:
Now I have UIScrollView where each Scrollbar item is a button item, containing title as the CategoryName.
I want to do the binding of CategoryName from the observable collection- to each scrollbar button title
Whenever the collection changes the buttons in the UISCrollView titles must reflect the change. What would be the binding expression in this case given the above class structures. Its challenging to figure out binding syntax.
Part 2:
I have a UITableView which would contain a cell having product title, product image and product cost, which means i have list
I want to bind this UITableView to this list which is part of Observable Collection->CategoryName->ProductData list
What would be the binding expression in this case. I hope we must do custom binding here.?
Yes as you said MvxTableViewCell etc., are available.
And regarding custom binding should I do it in the minisetup?
view models/data structures
In your data structures, you seem to be binding public fields instead of public properties.
These won't work straight away - you need to use properties
So:
public string CategoryName;
public class ProductData
{
public string ProductImageUri;
public string ProductTitle;
public float productcost;
}
need to become:
public string CategoryName {get;set;}
public class ProductData
{
public string ProductImageUri {get;set;}
public string ProductTitle {get;set;}
public float productcost {get;set;}
}
I am not able to find any of these classes: MvxCollectionViewSource, MvxTableViewCell, MvxCollectionViewController etc
MvxCollectionViewSource and MvxTableViewCell should be available in MvvmCross.Binding.Touch.dll
MvxCollectionViewController is not available - it's an MvvmCross View
In this case how can I achieve binding in CrossCore environment?
This is shown in the N+1 N=39 tutorial - http://slodge.blogspot.com.au/2013/09/n39-crosslight-on-xamariniosmonotouch.html - with source in https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-39-CrossLight-Touch
Also I should be able to do custom bindings?
Yes
But I am not having any setup class.. in my case. How can achieve custom binding in this case?
As shown in the N+1 N=39 tutorial, you still have a setup class - so you can put your initialization code in there. After the binding builder has been initialized, you can access the IMvxTargetBindingFactoryRegistry using Mvx.Resolve<IMvxTargetBindingFactoryRegistry>()
Because you are not using MvvmCross - because you are choosing to build your own framework - then ensuring setup is done is your own job to do.
What I am currently doing is have a view class and derive the view from IMvxBindable that's all and doing some binding in it
I have no idea what this means - please try including a working code sample in your questions.
I am designing a REST API one of my resources is all about to getting some basic data from user side.
Here are two points that I needs to mention:
all the user's information needs to send to server side with only one http request
the user's information is about 30 different fields.
So I think having a long list of argument in server side can not be that much good and I want to replace this part with a single argument which is accepting a JSON.
Do you think is it correct to do that?
Yes. You will want to change the method to a POST instead of a GET and in the request body send the JSON formatted data.
Example using C# syntax:
Assume you have a method that returns an object called ObjectList and in order to generate the list you the constructor requires an ObjectListRequest object -
public ObjectList GetObjectList(ObjectListRequest request)
{
return new ObjectList(request)
}
Your ObjectListRequest class could contain various different parameters that the request would use -
public class ObjectListRequest
{
public string SearchText { get; set; }
public string CreatedBy { get; set; }
public int SequenceStartRange { get; set; }
public int SequenceEndRange { get; set; }
public bool HasMetaData { get; set; }
}
Now to call this method using a POST with JSON in the body you would send the following
Method: POST
Url: http://your.service.com/GetObjectList
Headers:
Content-Type: application/json
Body:
{
"request":{
"SearchText":"test text",
"CreatedBy":"myusername",
"SequenceStartRange":0,
"SequenceEndRange":15,
"HasMetaData":"true"
}
}
This is a specific example which assumes you are using C# and built in Serialization libraries from microsoft, but if not, you can still use the same basic idea to do what you are trying to do.
Popular example: In the issue tracker JIRA, issues can be linked to other issues. The link itself has some data attached, in particular a type.
Example:
Issue A -> depends on -> Issue B
Issue B <- is depended on by <- Issue A
We are introducing the same kind of relationship for an entity in our C# ASP.NET MVC application using EF 4.1 CodeFirst, and I'm wondering how to best model this relationship?
Details:
There are some particularities about this situation:
A link has some data attached, so we can't simply model a many-to-many relationship between issues and issues. We rather have to introduce a new entity Link, which represents a relationship between two issues.
A link, by definition, links two instances of the same entity, it is a "two-to-many" relationship (a link has two issues, an issue can have many links).
The link is directed, which means, if Issue A depends on Issue B, then Issue B is depended on by Issue A.
We will certainly have a Link entity that looks like this:
public class Link
{
public int ID { get; set; }
public Issue IssueA { get; set; }
public Issue IssueB { get; set; }
public LinkType Type { get; set; }
}
The Issue class might look like this:
public class Issue
{
public int ID { get; set; }
public virtual ICollection<Link> Links { get; set; }
}
Currently there would be only one link type: dependency. So, the link type would look like this:
public class LinkType
{
public int ID { get; set; }
public string ForwardName { get; set; } // depends on
public string BackwardName { get; set; } // is depended on by
}
Now for the big question:
If I want EF to automatically manage Issue.Links, I have to tell it what Foreign key on the Link table to use. Either I use IssueA, or I use IssueB. I can't use both, can I?
Either I define:
modelBuilder.Entity<Issue>().HasMany(i => i.Links).WithRequired(l => l.IssueA);
or I define:
modelBuilder.Entity<Issue>().HasMany(i => i.Links).WithRequired(l => l.IssueB);
Possible approaches - I am curious about your feedback on whether some of them will lead to troubles, cannot be implemented, or whether any of these approaches can be regarded as "best practice":
Add two Collections to the Issue, ICollection<Link> OutgoingLinks, ICollection<Link> IncomingLinks. This way the collections can be maintained by EF, but from a business logic point of view they don't make much sense.
Only add one collection and configure EF 4.1 to add incoming and outgoing links to it, if that is possible.
Only add one collection and implement it on my own:
ICollection<Link> AllLinks { return _context.Links.Where(l => l.IssueA == this || l.IssueB == this).ToList(); }
The problem with this approach is that the domain entity executes data access tasks which is bad in terms of seperation of concerns.
Any other?
Option (1) is the way to go in my opinion, together with a readonly helper perhaps which combines the two collections:
public class Issue
{
public int ID { get; set; }
public virtual ICollection<Link> OutgoingLinks { get; set; }
public virtual ICollection<Link> InComingLinks { get; set; }
public IEnumerable<Link> Links // not mapped because readonly
{
get { return OutgoingLinks.Concat(InComingLinks); }
}
}
Option (2) isn't possible because you cannot map one navigation property to two different ends/navigation properties.
I am attempting to implement a tagging system into my asp.net MVC project. When a user edits or adds a task, they can add any amount of tags they want before submitting. I am using the Jquery Tagit plugin, so when a user adds a new tag an input field is created that looks like:
<input type="hidden" style="display:none;" value="tag1" name="Tags[]">
When the user presses the submit button after adding a few tags, the browser sends the following querystring to the server (retrieved via fiddler):
IsNew=True&Id=2222&Title=Test+Title&Description=Test+Description&Tags%5B%5D=Tag1&Tags%5B%5D=blah&Tags%5B%5D=another-tag
Now my viewmodel that I am serializing this data into has the following structure:
public class KnowledgeBaseTaskViewModel
{
public int Id { get; set; }
[Required(AllowEmptyStrings=false, ErrorMessage="Task title is required")]
[StringLength(500)]
public string Title { get; set; }
[Required(AllowEmptyStrings=false, ErrorMessage="Task description is required")]
[StringLength(500)]
public string Description { get; set; }
public List<string> Tags { get; set; }
public bool IsNew { get; set; } // Needed to determine if we are inserting or not
}
Finally my receiving action has the following signature:
[HttpPost]
public ActionResult EditTask(KnowledgeBaseTaskViewModel task)
The issue is that my tag list is not serializing correctly, and my List Tags is null. I have looked at various questions on this site on how to serialize arrays but I still cannot see what I am doing wrong. Any help is greatly appreciated.
It sounds like what you've got should work, but try changing the type of Tags property from List to IList. the model binder might not be using the concrete List<> type.
also, check out this article by Phil Haack: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx