FacebookClient DataTypes and enumeration - facebook

I would like to code using normal early binding datatypes rather than using dynamic (or var). However in order to enumerate using
foreach (var item in fbFeed.data)
requires that fbFeed is a type which has a property 'data'
var fb = new Facebook.FacebookClient(longlifeaccess_token);
dynamic fbFeed = fb.Get("me/feed");
foreach (var item in fbFeed.data)
{
var thepost = (IDictionary<string, object>)item;
Console.WriteLine("ID {0}", thepost["id"].ToString());
}
What data types should I be using for fbFeed and item in the above code, if I do not want to use var or dynamic.

I think this should be close
Facebook.FacebookClient fb = new Facebook.FacebookClient(longlifeaccess_token);
Facebook.JsonObject feFeed = (Facebook.JsonObject)fb.Get("me/feed");
Facebook.JsonArray feFeedData = (Facebook.JsonArray)feFeed["data"];
foreach (Facebook.JsonObject item in feFeedData)
{
IDictionary<string, object> post = (IDictionary<string, object>)item;
...
...

Related

Populating RITM Variables from a REST Call

I'm in the process of learning scripted REST API's. I have one that creates a REQ and RITM when the user does a POST. I'm having trouble populating variables from the rest post to the RITM. Below is my current code. Response is the RITM, Requester, and short description. I'm open to all suggestions, like I said I'm learning this on the fly, so if there is any glaring problems, I'm all ears. Thanks!
(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
var cartId = GlideGuid.generate(null);
var cart = new Cart(cartId);
var item = cart.addItem('25409830135aa20099fc7e776144b0a0');
var rc = cart.placeOrder();
var req = request.getHeader('ContactEmployeeId');
var sdesc = request.getHeader('ShortDescription');
//return rc.number;
//gs.addInfoMessage(rc.number);
var num = rc.sys_id; //get sys ID of newly created request
var rnum = 0;
//using the request number, query the RITM table for related RITM
var u = new GlideRecord('sc_req_item');
u.addEncodedQuery('request='+num);
u.query();
while ( u.next() )
{
rnum = u.number;
}
response.setBody({
Requested_Item: rnum,
u_requester: req,
short_description: sdesc
});
response.setContentType('application/json');
})(request, response);
You can use the setVariable(ritm, variableName, value) method such as this.
var cartId = GlideGuid.generate(null);
var cart = new Cart(cartId);
var item = cart.addItem('25409830135aa20099fc7e776144b0a0');
// add your variables here to the item variable in your cart object
cart.setVariable(item, "comments", message);
cart.setVariable(item, "my_var_1", value1);
cart.setVariable(item, "my_var_2", value2);
// submit order
var rc = cart.placeOrder();

Build dynamic LINQ queries from a string - Use Reflection?

I have some word templates(maybe thousands). Each template has merge fields which will be filled from database. I don`t like writing separate code for every template and then build the application and deploy it whenever a template is changed or a field on the template is added!
Instead, I'm trying to define all merge fields in a separate xml file and for each field I want to write the "query" which will be called when needed. EX:
mergefield1 will call query "Case.Parties.FirstOrDefault.NameEn"
mergefield2 will call query "Case.CaseNumber"
mergefield3 will call query "Case.Documents.FirstOrDefault.DocumentContent.DocumentType"
Etc,
So, for a particular template I scan its merge fields, and for each merge field I take it`s "query definition" and make that request to database using EntityFramework and LINQ. Ex. it works for these queries: "TimeSlots.FirstOrDefault.StartDateTime" or
"Case.CaseNumber"
This will be an engine which will generate word documents and fill it with merge fields from xml. In addition, it will work for any new template or new merge field.
Now, I have worked a version using reflection.
public string GetColumnValueByObjectByName(Expression<Func<TEntity, bool>> filter = null, string objectName = "", string dllName = "", string objectID = "", string propertyName = "")
{
string objectDllName = objectName + ", " + dllName;
Type type = Type.GetType(objectDllName);
Guid oID = new Guid(objectID);
dynamic Entity = context.Set(type).Find(oID); // get Object by Type and ObjectID
string value = ""; //the value which will be filled with data from database
IEnumerable<string> linqMethods = typeof(System.Linq.Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).Select(s => s.Name).ToList(); //get all linq methods and save them as list of strings
if (propertyName.Contains('.'))
{
string[] properies = propertyName.Split('.');
dynamic object1 = Entity;
IEnumerable<dynamic> Child = new List<dynamic>();
for (int i = 0; i < properies.Length; i++)
{
if (i < properies.Length - 1 && linqMethods.Contains(properies[i + 1]))
{
Child = type.GetProperty(properies[i]).GetValue(object1, null);
}
else if (linqMethods.Contains(properies[i]))
{
object1 = Child.Cast<object>().FirstOrDefault(); //for now works only with FirstOrDefault - Later it will be changed to work with ToList or other linq methods
type = object1.GetType();
}
else
{
if (linqMethods.Contains(properies[i]))
{
object1 = type.GetProperty(properies[i + 1]).GetValue(object1, null);
}
else
{
object1 = type.GetProperty(properies[i]).GetValue(object1, null);
}
type = object1.GetType();
}
}
value = object1.ToString(); //.StartDateTime.ToString();
}
return value;
}
I`m not sure if this is the best approach. Does anyone have a better suggestion, or maybe someone has already done something like this?
To shorten it: The idea is to make generic linq queries to database from a string like: "Case.Parties.FirstOrDefault.NameEn".
Your approach is very good. I have no doubt that it already works.
Another approach is using Expression Tree like #Egorikas have suggested.
Disclaimer: I'm the owner of the project Eval-Expression.NET
In short, this library allows you to evaluate almost any C# code at runtime (What you exactly want to do).
I would suggest you use my library instead. To keep the code:
More readable
Easier to support
Add some flexibility
Example
public string GetColumnValueByObjectByName(Expression<Func<TEntity, bool>> filter = null, string objectName = "", string dllName = "", string objectID = "", string propertyName = "")
{
string objectDllName = objectName + ", " + dllName;
Type type = Type.GetType(objectDllName);
Guid oID = new Guid(objectID);
object Entity = context.Set(type).Find(oID); // get Object by Type and ObjectID
var value = Eval.Execute("x." + propertyName, new { x = entity });
return value.ToString();
}
The library also allow you to use dynamic string with IQueryable
Wiki: LINQ-Dynamic

Testing With A Fake DbContext and Autofixture and Moq

SO follow this example
example and how make a fake DBContex For test my test using just this work fine
[Test]
public void CiudadIndex()
{
var ciudades = new FakeDbSet<Ciudad>
{
new Ciudad {CiudadId = 1, EmpresaId =1, Descripcion ="Santa Cruz", FechaProceso = DateTime.Now, MarcaBaja = null, UsuarioId = 1},
new Ciudad {CiudadId = 2, EmpresaId =1, Descripcion ="La Paz", FechaProceso = DateTime.Now, MarcaBaja = null, UsuarioId = 1},
new Ciudad {CiudadId = 3, EmpresaId =1, Descripcion ="Cochabamba", FechaProceso = DateTime.Now, MarcaBaja = null, UsuarioId = 1}
};
//// Create mock unit of work
var mockData = new Mock<IContext>();
mockData.Setup(m => m.Ciudades).Returns(ciudades);
// Setup controller
var homeController = new CiudadController(mockData.Object);
// Invoke
var viewResult = homeController.Index();
var ciudades_de_la_vista = (IEnumerable<Ciudad>)viewResult.Model;
// Assert..
}
Iam tryign now to use Autofixture-Moq
to create "ciudades" but I cant. I try this
var fixture = new Fixture();
var ciudades = fixture.Build<FakeDbSet<Ciudad>>().CreateMany<FakeDbSet<Ciudad>>();
var mockData = new Mock<IContext>();
mockData.Setup(m => m.Ciudades).Returns(ciudades);
I get this error
Cant convert System.Collections.Generic.IEnumerable(FakeDbSet(Ciudad)) to System.Data.Entity.IDbSet(Ciudad)
cant put "<>" so I replace with "()" in the error message
Implementation of IContext and FakeDbSet
public interface IContext
{
IDbSet<Ciudad> Ciudades { get; }
}
public class FakeDbSet<T> : IDbSet<T> where T : class
how can make this to work?
A minor point... In stuff like:
var ciudades_fixture = fixture.Build<Ciudad>().CreateMany<Ciudad>();
The second type arg is unnecessary and should be:
var ciudades_fixture = fixture.Build<Ciudad>().CreateMany();
I really understand why you need a FakeDbSet and the article is a bit TL;DR... In general, I try to avoid faking and mucking with ORM bits and instead dealing with interfaces returning POCOs to the max degree possible.
That aside... The reason the normal syntax for initialising the list works is that there is an Add (and IEnumerable) in DBFixture. AutoFixture doesn't have a story for that pattern directly (after all it is compiler syntactic sugar and not particularly amenable to reflection or in line with any other conventions) but you can use AddManyTo as long as there is an ICollection in play. Luckily, within the impl of FakeDbSet as in the article, the following gives us an in:-
public ObservableCollection<T> Local
{
get { return _data; }
}
As ObservableCollection<T> derives from ICollection<T>, you should be able to:
var ciudades = new FakeDbSet<Cuidad>();
fixture.AddManyTo(ciudades.Local);
var mockData = new Mock<IContext>();
mockData.Setup(m => m.Ciudades).Returns(ciudades);
It's possible to wire up a customization to make this prettier, but at least you have a way to manage it. The other option is to have something implement ICollection (or add a prop with a setter taking IEnumerable<T> and have AF generate the parent object, causing said collection to be filled in.
Long superseded side note: In your initial question, you effectively have:
fixture.Build<FakeDbSet<Ciudad>>().CreateMany()
The problem becomes clearer then - you are asking AF to generate Many FakeDbSet<Ciudad>s, which is not what you want.
I haven't used AutoFixture in a while, but shouldn't it be:
var ciudades = new FakeDbSet<Ciudad>();
fixture.AddManyTo(ciudades);
for the moment I end doing this, I will keep reading about how use automoq, cause I'm new in this
var fixture = new Fixture();
var ciudades_fixture = fixture.Build<Ciudad>().CreateMany<Ciudad>();
var ciudades = new FakeDbSet<Ciudad>();
foreach (var item in ciudades_fixture)
{
ciudades.Add(item);
}
var mockData = new Mock<IContext>();
fixture.Create<Mock<IContext>>();
mockData.Setup(r => r.Ciudades).Returns(ciudades);

Using Razor script to randomly pick a page node in Umbraco

The following code displays a testimonial item on the homepage of http://www.keelycattschoolofdance.co.uk which works nicely:
#using umbraco.MacroEngines;
#inherits umbraco.MacroEngines.DynamicNodeContext
#{
var numberOfItems = 1;
DynamicNodeList pages = #Model.Children.Where("umbracoNaviHide != true").Take(numberOfItems).OrderBy("UpdateDate");
}
<div>
#foreach (DynamicNode page in pages)
{
<h2>#page.Name</h2>
<p>#page.GetProperty("introText")</p>
<p>Read more...</p>
<p><strong>#page.GetProperty("personsName")</strong></p>
}
</div>
I would like to take this little script a stage further by selecting a random testimonial. How should I go about doing this?
try
var r = new Random();
var numberOfItems = 1;
List<DynamicNode> pages = new DynamicNode(Model.Id).Descendants().Items.Where(x => x.Visible).OrderBy(x => r.Next()).Take(numberOfItems).ToList();
I prefer the method of using Linq to generate random meta data and then sorting by it.
IPublishedContent containerNode = Umbraco.TypedContent(1144);
IPublishedContent randomlySelectedChildNode = containerNode.Children.OrderBy(n => Guid.NewGuid()).FirstOrDefault();
There is also a built-in Umbraco extension you can use:
var randomNode = containerNode.Children.RandomOrder().FirstOrDefault();
Try the ElementAt() Linq method:
Random r = new Random();
int max = 10; // set your own max
var items = #Model.Content.AncestorOrSelf(1).Descendants("SomeNode").First().Descendants("SomeChildNode").First().Children;
var item = items.ElementAt(r.Next(0, max)); // use linq ElementAt to retrieve your random node

Programmatically creating an Assign in a Flowchart Workflow

I need to programmatically define a serializable flowchart Windows Workflow that accepts input arguments and returns a result. I understand how to create these workflows using a designer, but I need to do it in code and have the flowchart workflow be serializable (so no lambda expressions).
I'm having trouble getting the "To" field of the Assign. The code below creates a flowchart workflow of a WriteLine followed by an Assign.
var ab = new ActivityBuilder<string> {
Name = "ActivityBuilt",
Implementation = new Flowchart {
StartNode = new FlowStep {
Action = new WriteLine { Text = new VisualBasicValue<string>("greeting") },
Next = new FlowStep {
Action = new Assign {
DisplayName = "Set result",
To = new OutArgument<string>(new VisualBasicReference<string> {
ExpressionText = "results"}),
Value = new VisualBasicValue<string>("bye")
}
}
}
}
};
ab.Properties.Add(new DynamicActivityProperty {
Name = "greeting",
Type = typeof (InArgument<string>),
Value = "hello"});
ab.Properties.Add(new DynamicActivityProperty {
Name = "results",
Type = typeof (OutArgument<string>),
Value = "bye"});
// Convert the ActivityBuilder to a callable activity
using (var sw = new StringWriter()) {
using (var xw = ActivityXamlServices.CreateBuilderWriter(new XamlXmlWriter(sw, new XamlSchemaContext()))) {
XamlServices.Save(xw, LastCreated);
}
using (var sr = new StringReader(sw.ToString())) {
var wf = ActivityXamlServices.Load(sr);
return wf;
}
}
The above code fails when I try to convert from ActivityBuilder to Activity saying "Failed to create a 'OutArgument' from the text 'bye'." This works fine if I don't use the OutArgument and just pass things in.
My question is what to put in the To property? How do I reference the OutArgument I add to the ActivityBuilder.Properties? A VisualBasicReference isn't an OutArgument. Am I making this more difficult than it needs to be?
Thanks for any hints!
Edit: I want to create a workflow programmatically. The workflow needs to have input arguments and return results (output arguments).
I understand how to create the workflow and how to declare and use input arguments. I'm using an ActivityBuilder to create the workflow and to set the InArgument via the ActivityBuilder's properties. I create the workflow from the ActivityBuilder by serializing to XAML and then deserializing using ActivityXamlServices.Load.
What I don't understand is how to get a result from the workflow. I assume it involves an OutArgument. How/where do I add an OutArgument to the workflow? I thought the code snippet I gave would assign a value to an OutArgument, but the call to ActivityXamlServices.Load fails with a complaint that it is unable to create the OutArgument.
Is the approach of using ActivityBuilder correct?
Is the "To" field of the Assign action properly referencing an OutArgument?
How do I make the ActivityBuilder aware of the OutArgument and still be able to convert to an Activity / workflow?
Hope this clarifies my problem.
There are atleast 3 problems with the code:
The Value of the Assign needs to be an InArgument().
The value you are trying to read from is named "greeting" not "bye".
The OutArgument named "results" can't have a default value.
Try the following code:
var ab = new ActivityBuilder<string>
{
Name = "ActivityBuilt",
Implementation = new Flowchart
{
StartNode = new FlowStep
{
Action = new WriteLine { Text = new VisualBasicValue<string>("greeting") },
Next = new FlowStep
{
Action = new Assign
{
DisplayName = "Set result",
To = new OutArgument<string>(new VisualBasicReference<string>
{
ExpressionText = "results"
}),
Value = new InArgument<string>(new VisualBasicValue<string>("greeting"))
}
}
}
}
};
ab.Properties.Add(new DynamicActivityProperty
{
Name = "greeting",
Type = typeof(InArgument<string>),
Value = "hello"
});
ab.Properties.Add(new DynamicActivityProperty
{
Name = "results",
Type = typeof(OutArgument<string>)
});
// Convert the ActivityBuilder to a callable activity
using (var sw = new StringWriter())
{
using (var xw = ActivityXamlServices.CreateBuilderWriter(new XamlXmlWriter(sw, new XamlSchemaContext())))
{
XamlServices.Save(xw, ab);
}
using (var sr = new StringReader(sw.ToString()))
{
var wf = ActivityXamlServices.Load(sr);
WorkflowInvoker.Invoke(wf);
}
}