Using Autonomy WorkSite 8.5 SP2 SDK, I am attempting to programmicaly add a shortcut to another users My Matters which I have been told can be done by first subscribing to the other users My Matters, add the shortcut then unsubscribe.
I am therefore attempting to subscribe to another users My Matters however I am having issues with how to subscribe, with the below code I am able to locate the user's My Matters:
Dim objSFSP As IManSubscriptionFolderSearchParameters = oDms.CreateSubscriptionFolderSearchParameters
objSFSP.Add( imFolderAttributeID.imFolderOwner, sShortcutUser )
Dim objFolders As IManFolders = oMatters.FindRootSubscriptionFoldersNotSubscribedTo(oDatabaseList, objSFSP)
And from reading the COM Reference guide I should be able to subscribe to a users My Matters with the following code:
Dim objWorkArea As IManWorkArea = oSess.WorkArea
Dim oFolderShortcuts As IManSubscriptionFolderShortcuts = objWorkArea.SubscriptionFolder.SubFolders
Dim oFolderShortcut As IManFolderShortcut = oFolderShortcuts.AddNewSubscriptionFolderShortcutInheriting(objFolders)
The problem I am encountering is AddNewSubscriptionFolderShortcutInheriting() expects an object of the type IManSubScriptionFolder where FindRootSubscriptionFoldersNotSubscribedTo() returns a IManFolders object.
Can anyone point me in the direction of what I need to do to get an instance of the users My Matters as a IManSubscriptionFolder object?
Probably my response will be a bit late for you, but I hope that it will help anybody else who will have the same issue.
Answering your question, in order to get an instance of other users My Matters as a IManSubscriptionFolder object you just need to loop through the collection of objFolders and cast each folder to the IManSubScriptionFolder type.
Please find below my working solution:
ManDMS dms = new ManDMS();
string serverName = "dms.server.com";
IManSession session = dms.Sessions.Add(serverName);
string userID = "user";
string password = "password";
session.Login(userID, password);
ManStrings dblist = new ManStrings();
dblist.Add("TargetWsDbName");
IManSubscriptionFolderSearchParameters searchParams = ndms.CreateSubscriptionFolderSearchParameters();
string folderOwner = "AnotherUser";
searchParams.Add(imFolderAttributeID.imFolderOwner, folderOwner);
IManFolders nonSubscribedRootSubscriptionFolders = session.WorkArea.SubscriptionFolder.FindRootSubscriptionFoldersNotSubscribedTo(dblist, searchParams);
foreach (var folder in nonSubscribedRootSubscriptionFolders)
{
//another user's subscription folder
var subscriptionFolder = folder as IManSubscriptionFolder;
if (subscriptionFolder != null)
{
//Current user's subscription folder shortcuts
var subscriptionFolderShortcuts = session.WorkArea.SubscriptionFolder.SubFolders as IManSubscriptionFolderShortcuts;
if (subscriptionFolderShortcuts != null)
{
subscriptionFolderShortcuts.AddNewSubscriptionFolderShortcutInheriting(subscriptionFolder);
}
}
Please note that code from above was included for reference purpose only and it is not a production code.
I have an ODataController with a Get method as such:
public IHttpActionResult Get(ODataQueryOptions<MyModel> queryOptions) {
IQueryable<MyModel> models = _Models.AsQueryable(); // _Models Defined in Controller as List<MyModel> and is already populated with nested data for both .LevelOne and .LevelOne.LevelTwo which are two other Lists.
Uri fullrequest = Request.GetRequestContext().Url.Request.RequestUri; // http://localhost:8080/odata/Root?$expand=LevelOne($expand=LevelTwo)
Uri serviceroot = new Uri(controller.GetLeftPart(UriPartial.Path).Replace("/Root", "")); // http://localhost:8080/odata
String metadata = service + "/$metadata"; // http://localhost:8080/odata/$metadata
IEdmModel model = EdmxReader.Parse(XmlTextReader.Create(metadata));
ODataUriParser parser = new ODataUriParser(model, serviceroot, fullrequest);
SelectExpandClause selectAndExpand = parser.ParseSelectAndExpand();
//Only one of the two below lines is ever commented in...
Request.ODataProperties().SelectExpandClause = queryOptions.SelectExpand.SelectExpandClause; // This line will work
Request.ODataProperties().SelectExpandClause = selectAndExpand; // This line will not work
return Ok(models);
}
using my manually parsed selectAndExpand does not expand the dataset, but using the predefined queryOptions one does. Any ideas why? Both objects appear to contain the same information while viewed in the debugger, but I must be missing something. I want to be able to parse the URI myself, without the need for the ODataQueryOptions at all.
What I ended up doing, was building a new ODataQueryOptions object based off the original request, and then pulling just the SelectExpandClause from that. It doesn't answer my initial question, but it is a somewhat working solution for not having to pass in a ODataQueryOptions parameter. See my Code below:
public IHttpActionResult Get() {
//Get Queryable Item (in this case just a list made queryable)
IQueryable<MyModel> models = _Models.AsQueryable();
//Create new ODataQueryContext based off initial request (required to create ODataQueryOptions)
ODataQueryContext selectAndExpandContext = new ODataQueryContext(Request.ODataProperties().Model, typeof(MyModel), Request.ODataProperties().Path);
//Create new ODataQueryOptions based off new context and original request
ODataQueryOptions<Employee> selectAndExpandOptions = new ODataQueryOptions<Employee>(selectAndExpandContext, Request);
//Attach Select + Expand options to be processed
if (selectAndExpandOptions.SelectExpand != null) {
Request.ODataProperties().SelectExpandClause = selectAndExpandOptions.SelectExpand.SelectExpandClause;
}
return Ok(models);
}
I've been trying to get a single entry from an IndexedDb instance using Dart's IndexedDb package. But I call getObject() which the documentation says returns a Future* (a Future of what I don't know) I don't have any Maps or other objects to work with.
What does the Future return in the store.getObject(id).then() method? If it doesn't return anything, how do I get information stored in the DB?
//within a TurnObjectStore class
Future<Turn> getTurn(int id){
Transaction t = _db.transaction(_TABLE_NAME, 'readonly');
ObjectStore store = t.objectStore(_TABLE_NAME);
return store.getObject(id).then((Map turn){
print('getTurn');
print(turn);
return turn;
});
}
A similar question is answered here indexed_db getObject() - how to return result but I'm getting warnings in my IDE when I try it that way and I'm wondering if the spec has changed since last year.
https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart-dom-indexed_db.ObjectStore#id_getObject
I am using Dart 1.2 and getObject(id) works fine.
I believe that the returned Future type depends on what is stored into your DB...
If you did save the data as a Map of your object, it will return a Map.
To store&restore your object as a Map, you can look at the official dart example for indexedDB:
// Serialize this to an object (a Map) to insert into the database.
Map toRaw() {
return {
'milestoneName': milestoneName,
'happensOn': happensOn.toString(),
};
}
//Create a Milestone based on the Map returned by the IndexedDB
Milestone.fromRaw(key, Map value):
dbKey = key,
milestoneName = value['milestoneName'],
happensOn = DateTime.parse(value['happensOn']) {
tick();
}
You can see the stored object directly from the developers tools of chrome, for a stored Map it should looks like this:
So i can get back the object with getObject:
var tr = mydb.transaction(myDB.CLIENT_STORE, 'readonly');
var st = tr.objectStore(myDB.CLIENT_STORE);
st.getObject(2).then((r){
Client client = new Client.fromRaw(2,r);
[...]
}
I am using the repository pattern in a asp.net mvc application (v3) and EntityFramework (v4).
I would like to add to the repository paging functionality. I have the following sample code:
public PagedResult<T> GetPaged(int offset = 0, int limit = PagedResult<T>.NoLimit, Expression<Func<T, bool>> predicate = null)
{
var res = BaseQ.Where(_predicate);//.Skip(offset);
if (predicate != null)
res = res.Where(predicate);
res = res.Skip(offset);
if (limit != PagedResult<T>.NoLimit)
{
res = res.Take(limit);
}
return new PagedResult<T>(res, res.Count(), offset, limit);
}
However, this will not work because Entity framework throws an exception that I should call OrderBy before Skip.
I am wondering how can I implement this in a generic way so that the order by expression will be plugged in from the outside. I would then pass it as a parameter.
Perhaps there is also another way of working around that problem.
[EDIT] I found out that this can be done by passing in the name of the property and creating an expression out of that, but I would like to actually just use it as I am using it in the OrderBy. So just pass in (c=>c.ID) for example.
Thanks in advance for any ideas
I have decided to go with passing in a string and creating the expression from it
I have an object which has a circular reference to another object. Given the relationship between these objects this is the right design.
To Illustrate
Machine => Customer => Machine
As is expected I run into an issue when I try to use Json to serialize a machine or customer object. What I am unsure of is how to resolve this issue as I don't want to break the relationship between the Machine and Customer objects. What are the options for resolving this issue?
Edit
Presently I am using Json method provided by the Controller base class. So the serialization I am doing is as basic as:
Json(machineForm);
Update:
Do not try to use NonSerializedAttribute, as the JavaScriptSerializer apparently ignores it.
Instead, use the ScriptIgnoreAttribute in System.Web.Script.Serialization.
public class Machine
{
public string Customer { get; set; }
// Other members
// ...
}
public class Customer
{
[ScriptIgnore]
public Machine Machine { get; set; } // Parent reference?
// Other members
// ...
}
This way, when you toss a Machine into the Json method, it will traverse the relationship from Machine to Customer but will not try to go back from Customer to Machine.
The relationship is still there for your code to do as it pleases with, but the JavaScriptSerializer (used by the Json method) will ignore it.
I'm answering this despite its age because it is the 3rd result (currently) from Google for "json.encode circular reference" and although I don't agree with the answers (completely) above, in that using the ScriptIgnoreAttribute assumes that you won't anywhere in your code want to traverse the relationship in the other direction for some JSON. I don't believe in locking down your model because of one use case.
It did inspire me to use this simple solution.
Since you're working in a View in MVC, you have the Model and you want to simply assign the Model to the ViewData.Model within your controller, go ahead and use a LINQ query within your View to flatten the data nicely removing the offending circular reference for the particular JSON you want like this:
var jsonMachines = from m in machineForm
select new { m.X, m.Y, // other Machine properties you desire
Customer = new { m.Customer.Id, m.Customer.Name, // other Customer properties you desire
}};
return Json(jsonMachines);
Or if the Machine -> Customer relationship is 1..* -> * then try:
var jsonMachines = from m in machineForm
select new { m.X, m.Y, // other machine properties you desire
Customers = new List<Customer>(
(from c in m.Customers
select new Customer()
{
Id = c.Id,
Name = c.Name,
// Other Customer properties you desire
}).Cast<Customer>())
};
return Json(jsonMachines);
Based on txl's answer you have to
disable lazy loading and proxy creation and you can use the normal methods to get your data.
Example:
//Retrieve Items with Json:
public JsonResult Search(string id = "")
{
db.Configuration.LazyLoadingEnabled = false;
db.Configuration.ProxyCreationEnabled = false;
var res = db.Table.Where(a => a.Name.Contains(id)).Take(8);
return Json(res, JsonRequestBehavior.AllowGet);
}
Use to have the same problem. I have created a simple extension method, that "flattens" L2E objects into an IDictionary. An IDictionary is serialized correctly by the JavaScriptSerializer. The resulting Json is the same as directly serializing the object.
Since I limit the level of serialization, circular references are avoided. It also will not include 1->n linked tables (Entitysets).
private static IDictionary<string, object> JsonFlatten(object data, int maxLevel, int currLevel) {
var result = new Dictionary<string, object>();
var myType = data.GetType();
var myAssembly = myType.Assembly;
var props = myType.GetProperties();
foreach (var prop in props) {
// Remove EntityKey etc.
if (prop.Name.StartsWith("Entity")) {
continue;
}
if (prop.Name.EndsWith("Reference")) {
continue;
}
// Do not include lookups to linked tables
Type typeOfProp = prop.PropertyType;
if (typeOfProp.Name.StartsWith("EntityCollection")) {
continue;
}
// If the type is from my assembly == custom type
// include it, but flattened
if (typeOfProp.Assembly == myAssembly) {
if (currLevel < maxLevel) {
result.Add(prop.Name, JsonFlatten(prop.GetValue(data, null), maxLevel, currLevel + 1));
}
} else {
result.Add(prop.Name, prop.GetValue(data, null));
}
}
return result;
}
public static IDictionary<string, object> JsonFlatten(this Controller controller, object data, int maxLevel = 2) {
return JsonFlatten(data, maxLevel, 1);
}
My Action method looks like this:
public JsonResult AsJson(int id) {
var data = Find(id);
var result = this.JsonFlatten(data);
return Json(result, JsonRequestBehavior.AllowGet);
}
In the Entity Framework version 4, there is an option available: ObjectContextOptions.LazyLoadingEnabled
Setting it to false should avoid the 'circular reference' issue. However, you will have to explicitly load the navigation properties that you want to include.
see: http://msdn.microsoft.com/en-us/library/bb896272.aspx
Since, to my knowledge, you cannot serialize object references, but only copies you could try employing a bit of a dirty hack that goes something like this:
Customer should serialize its Machine reference as the machine's id
When you deserialize the json code you can then run a simple function on top of it that transforms those id's into proper references.
You need to decide which is the "root" object. Say the machine is the root, then the customer is a sub-object of machine. When you serialise machine, it will serialise the customer as a sub-object in the JSON, and when the customer is serialised, it will NOT serialise it's back-reference to the machine. When your code deserialises the machine, it will deserialise the machine's customer sub-object and reinstate the back-reference from the customer to the machine.
Most serialisation libraries provide some kind of hook to modify how deserialisation is performed for each class. You'd need to use that hook to modify deserialisation for the machine class to reinstate the backreference in the machine's customer. Exactly what that hook is depends on the JSON library you are using.
I've had the same problem this week as well, and could not use anonymous types because I needed to implement an interface asking for a List<MyType>. After making a diagram showing all relationships with navigability, I found out that MyType had a bidirectional relationship with MyObject which caused this circular reference, since they both saved each other.
After deciding that MyObject did not really need to know MyType, and thereby making it a unidirectional relationship this problem was solved.
What I have done is a bit radical, but I don't need the property, which makes the nasty circular-reference-causing error, so I have set it to null before serializing.
SessionTickets result = GetTicketsSession();
foreach(var r in result.Tickets)
{
r.TicketTypes = null; //those two were creating the problem
r.SelectedTicketType = null;
}
return Json(result);
If you really need your properties, you can create a viewmodel which does not hold circular references, but maybe keeps some Id of the important element, that you could use later for restoring the original value.