How to configure links with HasNavigationPropertiesLink after latest WebAPI beta (26-Jun-2013) Update - asp.net

I have a basic POCO (No database) structure implementing an OData Service with the latest WebAPI update. Unfortunately, the latest update broke the HasNavigationPropertiesLink code that I had to generate links which can be used for $expand operations. Here is my old code:
var jobs = modelBuilder.EntitySet<Job>("Jobs");
jobs.EntityType.NavigationProperties,
(entityContext, navigationProperty) => new
Uri(entityContext.UrlHelper.Link(ODataRouteNames.PropertyNavigation,
new
{
Controller = "Jobs",
parentId = entityContext.EntityInstance.ID,
NavigationProperty = navigationProperty.Name
})));
And here is my new code (that doesn't work):
var jobs = modelBuilder.EntitySet<Job>("Jobs");
jobs.EntityType.NavigationProperties,
(entityContext, navigationProperty) => new
Uri(entityContext.Url.Link(<??WHAT GOES HERE??>,
new
{
Controller = "Jobs",
parentId = entityContext.EdmObject,
NavigationProperty = navigationProperty.Name
})),
true);
Any help is much appreciated - this doesn't seem to have been documented in the updates.

looks like the version of the OData bits you are using is very old. In our current version, you can use the ODataConventionsModelBuilder to create a model that defines navigation properties and links following conventions, so unless you need to generate custom links, it's a better way to go. However, if you want to generate a custom navigation link, the link generation code looks something similar to this:
var jobs = builder.EntitySet<Job>("Jobs");
jobs.HasNavigationPropertiesLink(customers.EntityType.NavigationProperties,
(context, navigationProperty) =>
{
var result = "http://mydomain.com/prefix/odataPath";
//In order to generate this link you can use context.Url.ODataLink(new EntityPathSegment("Jobs"), ...);
return new Uri(result);
}, followsConventions: true);

it is better to use ODataConventionsModelBuilder as Javier has suggested. But if you still want to set up your own odata model you can do it:
var jobs = builder.EntitySet<Job>("Jobs");
jobs.HasNavigationPropertiesLink(customers.EntityType.NavigationProperties,
(context, navigationProperty) => context.GenerateNavigationPropertyLink(navigationProperty, false)
, followsConventions: true);

Related

What does "new[]" mean with ReactiveCommand C# and how does this code execute?

I am creating an application using Firebase Firestore and Plugin.CloudFirestore for Xamarin Forms based off of the Sample Project posted on the plugin's GitHub (link:
https://github.com/f-miyu/Plugin.CloudFirestore).
I am trying to learn how to write Async Reactive Commands based off of how they are written in the sample project but I'm having a really hard time reverse engineering this code.
UpdateCommand = new[] {
_todoItem.Select(x => x == null),
Name.Select(x => string.IsNullOrEmpty(x))
}.CombineLatestValuesAreAllFalse()
.ObserveOn(SynchronizationContext.Current)
.ToAsyncReactiveCommand();
UpdateCommand.Subscribe(async () =>
{
var todoItem = _todoItem.Value;
todoItem.Name = Name.Value;
todoItem.Notes = Notes.Value;
_ = CrossCloudFirestore.Current.Instance.Document($"{TodoItem.CollectionPath}/{todoItem.Id}")
.UpdateAsync(todoItem)
.ContinueWith(t =>
{
System.Diagnostics.Debug.WriteLine(t.Exception);
}, TaskContinuationOptions.OnlyOnFaulted);
await navigationService.GoBackAsync();
});
This code snippet is from the "TodoItemDetailPageViewModel.cs" file within the sample project if you would like more context.
The code above updates the field values of the document that is selected from the main page via the Firestore API. The code is working but I don't have any idea what the above code means and how the command works. Could someone break it down for me and explain what is going on? I am sure someone else could benefit as well.
Thanks

how to get all content items of a special content type in orchad core

I'm working with orchard core and I've written my own Apis.
To get content items of a special content type I've used GetRecentContentItemsByContentTypeAsync() function. this function does not get all content items, but I need to get all to write a service with pagination.
I would appreciate it if there is a solution...
Thanks in advance
You probably will want to use inject the YesSql.ISession directly to create a more specific query.
Something like
var query = _session.Query<ContentItem, ContentItemIndex>(x => x.ContentType == "mycontenttype");
var count = await query.CountAsync(); // for pagination
var results = await query.Skip(0).Take(10).ListAsync();
or for a more complex set
using YesSql.Services;
var contentTypes = new [ "contenttype1", "contenttype2" ];
var query = _session.Query<ContentItem, ContentItemIndex>(x => x.ContentType.IsIn(contentTypes));

Using CSOM to update multiple tasks with only 1 project publish

I have the following code that updates certain task fields. The problem with this code is that I have to publish an entire project after updating each task one-by-one. So for example, if I had 500 tasks to update, the project would have to be published 500 times. As you can see, this is completely overkill, slow and unnecessary.
using (ProjectContext projectContext = GetClientContext(psCred))
{
projectContext.Load(projectContext.Projects);
projectContext.ExecuteQuery();
foreach (var project in projectContext.Projects)
{
var draftProject = project.CheckOut();
projectContext.Load(draftProject.Tasks);
projectContext.ExecuteQuery();
projectContext.Load(draftProject.Task);
projectContext.ExecuteQuery();
foreach (var task in draftProject.Tasks)
{
task["FIELD"] = "VALUE";
var job = draftProject.Update();
projectContext.WaitForQueue(job, int.MaxValue);
job = draftProject.Publish(true);
projectContext.WaitForQueue(job, int.MaxValue);
}
}
}
I hope there is a way to update update all of the project tasks at once with only one publish at the end just like how Microsoft Project desktop application does it.
For what it's worth, I was able to create a bunch of tasks and then use this code to update a custom field on all of the new/existing tasks with a single publish:
DraftProject projCheckedOut = proj2Edit.CheckOut();
_projContext.Load(projCheckedOut.Tasks, ts =>
ts.Include(
t => t.Id,
t => t.Name,
t => t.CustomFields,
t => t.OutlineLevel,
t => t.IsSummary));
_projContext.ExecuteQuery();
// Lookup custom field internal name from our StringDictionary
string intNamePref = _customFields["Custom Field1"];
var tasks = projCheckedOut.Tasks;
foreach (var t in tasks)
{
t[intNamePref] = 2;
}
projCheckedOut.Publish(true);
_projContext.ExecuteQuery();
Tip, to get the .Include lambda to work, I had to add this using:
using Microsoft.SharePoint.Client;

AngularFire extending the service issue

I've been looking at the documentation for Synchronized Arrays https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-extending-the-services and https://www.firebase.com/docs/web/libraries/angular/guide/extending-services.html#section-firebasearray
I'm using Firebase version 2.2.7 and AngularFire version 1.1.2
Using the code below, I'm having trouble recognizing $$removed events.
.factory("ExtendedCourseList", ["$firebaseArray", function($firebaseArray) {
// create a new service based on $firebaseArray
var ExtendedCourseList= $firebaseArray.$extend({
$$added: function(dataSnapshot, prevChild){
var course = dataSnapshot.val();
var course_key = dataSnapshot.key();
console.log("new course");
return course;
},
$$removed: function(snap){
console.log("removed");
return true;
}
});
return function(listRef) {
return new ExtendedCourseList(listRef);
}
}])
.factory("CompanyRefObj", function(CompanyRef) {
//CompanyRef is a constant containing the url string
var ref = new Firebase(CompanyRef);
return ref;
})
.factory('CourseList', function (localstorage,$rootScope,ExtendedCourseList,CompanyRefObj) {
var companyID = localstorage.get("company");
$rootScope.courseList = ExtendedCourseList(CompanyRefObj.child(companyID).child("courses"));
)
If I run this code, only the $$added events will be triggered. To simulate the remove events I use the web-interface at Firebase to display data, where I press the remove button and accept the data being deleted permanently.
Additionally, if I delete the $$removed function, the extended service still won't synchronize when a record is deleted.
If I modify my code to use the $firebaseArray instead of extending the service (as seen above) both add and remove events will be recognized.
.factory('CourseList', function (localstorage,$rootScope,$firebaseArray,CompanyRefObj) {
var companyID = localstorage.get("company");
$rootScope.courseList = $firebaseArray(CompanyRefObj.child(companyID).child("courses"));
)
Finally, are there any bad practices I've missed that can cause some of the extended functions to not work?
Solved
$$added: function(dataSnapshot, prevChild){
var course = dataSnapshot.val();
var course_key = dataSnapshot.key();
//Modified below
course.$id = course_key;
//End of modification
console.log("new course");
return course;
}
After posting about the issue at firebase/angularfire github I received an answer that solved my issue. When $$added got overridden by the code provided, the $firebaseArray also lost its internal record $id.
Adding this line of code: course.$id = course_key; before returning the course, made AngularFire recognize when the record was removed from the server.

firebaseObject $save() replaces the content of reference

I can't make $save() work (i'm using firebaseObject)
var user = new Firebase("URL");
user.name = 'mark';
user.$save();
After this my user's all records are simply replaced by a single
name: mark
The data isn't loaded yet in your example. You'll have to wait by hooking into the firebase .on or (as it seems you're using angularfire) you can look into working with $loaded based on the reference.
var user = $firebaseObject(new Firebase("URL"));
user.$loaded().then(function(){
user.name = 'mark';
user.$save();
});
Actually, i missed the $firebaseObject in code sample above.
The problem was that my firebaseObject was not loaded yet. $loaded() fixed it. Here is the final working code:
var user = $firebaseObject(new Firebase("URL"));
user.$loaded().then(function(){
user.name = 'mark';
user.$save();
});

Resources