How to get a Sitecore item from a fake site - c#

In a unittest I am using Sitecore.FakeDb.
I have extended the sample to add the fakeSite with a rootPath, which gets set.
If I try to retrieve the rootItem with Context.Site.GetItem(rootPath) it returns null.
[Test]
public void FakeSite()
{
// create a fake site context
var fakeSite = new Sitecore.FakeDb.Sites.FakeSiteContext(
new Sitecore.Collections.StringDictionary
{
{ "name", "website" }, { "database", "web" }, { "rootPath", "/sitecore/content/NL" }
});
// switch the context site
using (new Sitecore.Sites.SiteContextSwitcher(fakeSite))
{
var rootItem = Context.Site.Database.GetItem(Context.Site.RootPath); // returns null
Assert.IsNotNull(rootItem);
Assert.AreEqual("website", Sitecore.Context.Site.Name);
Assert.AreEqual("master", Sitecore.Context.Site.Database.Name);
}
}
What am I missing?

You need to add fake item to your fake db first.
See sample code from github here:
public void HowToCreateSimpleItem()
{
using (Sitecore.FakeDb.Db db = new Sitecore.FakeDb.Db
{
new Sitecore.FakeDb.DbItem("Home") { { "Title", "Welcome!" } }
})
{
Sitecore.Data.Items.Item home = db.GetItem("/sitecore/content/home");
Xunit.Assert.Equal("Welcome!", home["Title"]);
}
}
public void HowToCreateHierarchyOfItems()
{
using (Sitecore.FakeDb.Db db = new Sitecore.FakeDb.Db
{
new Sitecore.FakeDb.DbItem("Articles")
{
new Sitecore.FakeDb.DbItem("Getting Started"),
new Sitecore.FakeDb.DbItem("Troubleshooting")
}
})
{
Sitecore.Data.Items.Item articles =
db.GetItem("/sitecore/content/Articles");
Xunit.Assert.NotNull(articles.Children["Getting Started"]);
Xunit.Assert.NotNull(articles.Children["Troubleshooting"]);
}
}
https://github.com/sergeyshushlyapin/Sitecore.FakeDb/wiki/Creating-a-Simple-Item
https://github.com/sergeyshushlyapin/Sitecore.FakeDb/wiki/Creating-a-Hierarchy-of-Items

As #Marek said, I didn't create an item, just set the rootPath to which item it should point.
This is the working test.
[Test]
public void FakeSite()
{
using (Db db = new Db("web")
{
new DbItem("NL") { { "Title", "NL Site" } }
})
{
Item siteItem = db.GetItem("/sitecore/content/NL");
// create a fake site context
var fakeSite = new Sitecore.FakeDb.Sites.FakeSiteContext(
new Sitecore.Collections.StringDictionary
{
{ "name", "website" }, { "database", "web" }, { "rootPath", "/sitecore/content/NL" }
});
// switch the context site
using (new Sitecore.Sites.SiteContextSwitcher(fakeSite))
{
Assert.AreEqual("website", Sitecore.Context.Site.Name);
Assert.AreEqual("web", Sitecore.Context.Site.Database.Name);
var rootItem = Context.Site.Database.GetItem(Context.Site.RootPath);
Assert.IsNotNull(rootItem);
}
}
}
Although I realize that Site means the CM/CD site. Not the MultiSite I was looking for.

Related

Moq keeps throwing null reference exception

I am new to Moq having used Rhino mocks for a while. I am trying to stub a method so that is returns the information I expect but the actual line of code when running the test returns a null reference exception. Am I missing something obvious here? Below is my code:
public void GetResSystemClients(ResSystem resSystem)
{
ResSystemDetail = new ResSystemDetails() {ResSys = resSystem};
//RETURNS NULL REFERENCE EXCEPTION
var resClients = FileReader.ReadFile((c) => c.Where(x =>
x.ReservationSystem.Replace(" ", "").ToLowerInvariant().Contains(resSystem.ToString().ToLowerInvariant())));
ResSystemDetail.ResSystemClients = resClients
.Select(y => new ResSystemClient() {ClientCode = y.ClientCode, ClientName = y.ClientName})
.OrderBy(z => z.ClientCode).ToList();
}
Test Code
[SetUp]
public void SetUp()
{
mockFileReader = new Mock<IClientLookUpFileReader>(MockBehavior.Default);
sut = new ClientLookupModel();
}
[TestCase(ResSystem.Test)]
public void When_GetResSystemCalled_With_ResSystem_Return_CorrectClients(ResSystem system)
{
//Arrange
mockFileReader.Setup(x =>
x.ReadFile(It.IsAny<Func<List<ExtraClientInfo>, IEnumerable<ExtraClientInfo>>>()))
.Returns(new List<ExtraClientInfo>
{
new ExtraClientInfo
{
ClientName = "Test",
ClientCode = "XX"
},
new ExtraClientInfo
{
ClientName = "Test1",
ClientCode = "X1"
},
new ExtraClientInfo
{
ClientName = "Test2",
ClientCode = "X2"
},
});
//Act
sut.GetResSystemClients(system);
}
Read file code
public interface IClientLookUpFileReader
{
T ReadFile<T>(Func<List<ExtraClientInfo>, T> predicateFunc);
}
public class ClientLookUpFileReader : IClientLookUpFileReader
{
private const string filePath = "D:/PersistedModels/ClientInfo.json";
T IClientLookUpFileReader.ReadFile<T>(Func<List<ExtraClientInfo>, T> predicateFunc)
{
if (File.Exists(filePath))
{
var clientInfoList = new JavaScriptSerializer().Deserialize<List<ExtraClientInfo>>(System.IO.File.ReadAllText(filePath));
return predicateFunc(clientInfoList);
}
throw new Exception($"File not found at path {filePath}");
}
}

How to Create hierarchical Item source for my hierarchial datatemplate from datatable

I'm trying to make a hierarchical item source from a datatable whose fields are(Unique_id,Lookup_Value,Parent_Id,Is_Parent,Category_Level) where each record either be a parent or child. I'm trying with recursion but multilevel cannot be achieved. How can it be?
1.first i have filtered all parent nodes where is_parent=true;
2.i have passed each root to a recursive method for finding its child.
i have achieved two level.
private void CreateHierarchicalScanningCategory(DataTable scanningcategory)
{
Task<List<ScanningMenuItem>> scaningmenuitem =
Task.Factory.StartNew(() => CreateHierarchicalTemplate(scanningcategory));
}
private List<ScanningMenuItem> CreateHierarchicalTemplate(DataTable scanningcategory)
{
Func<DataRow, ScanningMenuItem, ScanningMenuItem> _funcfor_parentchild = null;
_funcfor_parentchild = (parentrow, menuitem) =>
{
var childrows = this._scanning_Category.AsEnumerable().Where
(row => Convert.ToInt32(row["Parent_Id"]) == Convert.ToInt32(parentrow["Gen_Lookup_Id"]));
if (childrows != null && childrows.Any())
{
foreach (var item in childrows)
{
var foo = new ScanningMenuItem { Title = Convert.ToString(item["Lookup_Value"]) };
menuitem.Items.Add(foo);
_funcfor_parentchild(item, menuitem);
}
}
return menuitem;
};
var parentnodes = scanningcategory.Copy().AsEnumerable().Where(row => Convert.ToBoolean(row["Is_Parent"]) == true);
if (parentnodes.Any())
{
List<ScanningMenuItem> menuitem = new List<ScanningMenuItem>();
foreach (var item in parentnodes)
{
ScanningMenuItem root = new ScanningMenuItem { Title = Convert.ToString(item["Lookup_Value"]) };
var node_menuitem = _funcfor_parentchild(item, root);
menuitem.Add(node_menuitem);
}
return menuitem;
}
return null;
}
ScanningMenuItem:
public class ScanningMenuItem
{
public ScanningMenuItem()
{
this.Items = new ObservableCollection<ScanningMenuItem>();
}
public string Title { get; set; }
public ObservableCollection<ScanningMenuItem> Items { get; set; }
}
Datatable structure:
DataTable dt = new DataTable
{
Columns = { { "Unique_id", typeof(int) },
{"Lookup_Value" }, {"Parent_Id",typeof(int) },
{ "Is_Parent",typeof(int) }, {"Category_Level",typeof(int) } }
};
dt.Rows.Add(150, "EMR",0,1,1);
dt.Rows.Add(100361, "Cardiology",150,0,2);
dt.Rows.Add(100362, "Gastrology",150,0,2);
dt.Rows.Add(152, "Discharge Summary",0,1,1);
dt.Rows.Add(1385,"Investigations/Procedures", 0, 1, 1);
dt.Rows.Add(1700, "DENTAL",0,1,1);
dt.Rows.Add(633671, "EMR2",0, 1,1);
dt.Rows.Add(151, "FO",0, 1,1);
dt.Rows.Add(117370,"External Sick Leave",151, 0, 2);
dt.Rows.Add(117371,"External Appointment",151, 0, 2);
dt.Rows.Add(117372,"Heart Transplantation",100361, 0, 3);
The Datatable is dynamic. don't know how many levels are coming.
1.EMR
1.1 Cardiology
1.1.1 Heart Transplantation
1.2 Gastrology
2.FO
2.1 External Appointment
2.2 External Appointment
3.EMR2
3.1 Discharge
3.2 DENTAL
3.3 Investigations/Procedures"`enter code here`

Method inside an array in C#

I just got in contact with C# and I was wondering if it's possible to call a method inside an array. I have to say that I'm working with NoSQL database (mongodb).
This is mi code, and I want to call data() method inside that JSON.
static void Main(string[] args)
{
MongoClient client = new MongoClient();
var db = client.GetDatabase("test");
var collection = db.GetCollection<BsonDocument>("collection");
var document = new BsonDocument
{
{ "date", 10/04/2018 },
{ "data", data() }
};
collection.InsertOneAsync(document);
Console.Read();
}
static void data()
{
for (int i = 1; i <= 50; i++)
{
var data = new BsonDocument
{
{ "magnitude"+i, new BsonDocument{
{ "value", 5 }
} }
};
}
}
EDIT: Basically, what I'm trying to create with C# is this json below. I already did it with PHP and now, I'm trying to do it with C#.
{
"_id" : ObjectId("5abb735eb57dce214009035a"),
"date" : 1262300400,
"data" : {
"magnitude1" : {
"value" : 60
},
"magnitude2" : {
"value" : 38
},
"magnitude3" : {
"value" : 200
},
"magnitude4" : {
"value" : 62
},
"magnitude5" : {
"value" : 153
},
"magnitude6" : {
"value" : 176
},
"magnitude7" : {
"value" : 185
},
"magnitude8" : {
"value" : 168
},
.
.
.
You can use methods to gather data but I'm not sure exactly how you're asking it. Related to the code example I'll just give a simple run down, which is basic programming in general, not just C#.
You can write methods that return void or that return a variable of some type (at a minimum).
//Returns void
public void DoSomething()
{
//Do some work
return;
}
//Returns int
public int GetSomething()
{
int result = 100;
return result;
}
When you have methods that return data you can use them as you would a variable; just remember the method will execute every time it's called so it's often best to save the data to a variable. But for your example you can do something like this.
//other code ommitted
var document = new BsonDocument
{
{ "date", 10/04/2018 },
{ "data", getDocuments() }
};
//remaining code omitted
static List<BsonDocument> getDocuments()
{
var documents = new List<BsonDocument>();
for (int i = 1; i <= 50; i++)
{
var document = new BsonDocument
{
{ "magnitude" + i, new BsonDocument { { "value", 5 } } }
};
documents.Add(document);
}
return documents;
}
Now I modified the data() method to return a list of documents and changed the naming to match it but I'm not sure what you wanted to do with the method. That was my best assumption of what you were trying to accomplish by looking at your code so feel free to ignore all of it if it's wrong.
I've could solve it thanks to #Michael .Code below in case helps to anyone.
static void Main(string[] args)
{
MongoClient client = new MongoClient();
var db = client.GetDatabase("test");
var collection = db.GetCollection<BsonDocument>("Collection");
var document = new BsonDocument
{
{ "date", 10/04/2018 },
{ "data", new BsonDocument{ getDocuments() } }
};
collection.InsertOneAsync(document);
Console.Read();
}
static BsonDocument getDocuments()
{
var documents = new BsonDocument();
for (int i = 1; i <= 5; i++)
{
var document = new BsonDocument
{
{ "magnitude" + i, new BsonDocument { { "value", 5 } } }
};
documents.AddRange(document);
}
return documents;
}

Use workflow to evaluate dynamic expression

I would like to pass an object and expression into a dynamically created workflow to mimic the Eval function found in many languages. Can anyone help me out with what I am doing wrong? The code below is a very simple example if taking in a Policy object, multiple its premium by 1.05, then return the result. It throws the exception:
Additional information: The following errors were encountered while processing the workflow tree:
'DynamicActivity': The private implementation of activity '1: DynamicActivity' has the following validation error: Value for a required activity argument 'To' was not supplied.
And the code:
using System.Activities;
using System.Activities.Statements;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Policy p = new Policy() { Premium = 100, Year = 2016 };
var inputPolicy = new InArgument<Policy>();
var theOutput = new OutArgument<object>();
Activity dynamicWorkflow = new DynamicActivity()
{
Properties =
{
new DynamicActivityProperty
{
Name="Policy",
Type=typeof(InArgument<Policy>),
Value=inputPolicy
}
},
Implementation = () => new Sequence()
{
Activities =
{
new Assign()
{
To = theOutput,
Value=new InArgument<string>() { Expression = "Policy.Premium * 1.05" }
}
}
}
};
WorkflowInvoker.Invoke(dynamicWorkflow);
}
}
public class Policy
{
public int Premium { get; set; }
public int Year { get; set; }
}
}
You can use Workflow Foundation to evaluate expressions, but it is far easier to use almost any other option.
The key issue at play with your code was that you were not trying to evaluate the expression (with either VisualBasicValue or CSharpValue). Assigning InArgument`1.Expression is an attempt to set the value - not to set the value to the result of an expression.
Keep in mind that compiling expressions is fairly slow (>10ms), but the resultant compiled expression can be cached for quick executions.
Using Workflow:
class Program
{
static void Main(string[] args)
{
// this is slow, only do this once per expression
var evaluator = new PolicyExpressionEvaluator("Policy.Premium * 1.05");
// this is fairly fast
var policy1 = new Policy() { Premium = 100, Year = 2016 };
var result1 = evaluator.Evaluate(policy1);
var policy2 = new Policy() { Premium = 150, Year = 2016 };
var result2 = evaluator.Evaluate(policy2);
Console.WriteLine($"Policy 1: {result1}, Policy 2: {result2}");
}
}
public class Policy
{
public double Premium, Year;
}
class PolicyExpressionEvaluator
{
const string
ParamName = "Policy",
ResultName = "result";
public PolicyExpressionEvaluator(string expression)
{
var paramVariable = new Variable<Policy>(ParamName);
var resultVariable = new Variable<double>(ResultName);
var daRoot = new DynamicActivity()
{
Name = "DemoExpressionActivity",
Properties =
{
new DynamicActivityProperty() { Name = ParamName, Type = typeof(InArgument<Policy>) },
new DynamicActivityProperty() { Name = ResultName, Type = typeof(OutArgument<double>) }
},
Implementation = () => new Assign<double>()
{
To = new ArgumentReference<double>() { ArgumentName = ResultName },
Value = new InArgument<double>(new CSharpValue<double>(expression))
}
};
CSharpExpressionTools.CompileExpressions(daRoot, typeof(Policy).Assembly);
this.Activity = daRoot;
}
public DynamicActivity Activity { get; }
public double Evaluate(Policy p)
{
var results = WorkflowInvoker.Invoke(this.Activity,
new Dictionary<string, object>() { { ParamName, p } });
return (double)results[ResultName];
}
}
internal static class CSharpExpressionTools
{
public static void CompileExpressions(DynamicActivity dynamicActivity, params Assembly[] references)
{
// See https://learn.microsoft.com/en-us/dotnet/framework/windows-workflow-foundation/csharp-expressions
string activityName = dynamicActivity.Name;
string activityType = activityName.Split('.').Last() + "_CompiledExpressionRoot";
string activityNamespace = string.Join(".", activityName.Split('.').Reverse().Skip(1).Reverse());
TextExpressionCompilerSettings settings = new TextExpressionCompilerSettings
{
Activity = dynamicActivity,
Language = "C#",
ActivityName = activityType,
ActivityNamespace = activityNamespace,
RootNamespace = null,
GenerateAsPartialClass = false,
AlwaysGenerateSource = true,
ForImplementation = true
};
// add assembly references
TextExpression.SetReferencesForImplementation(dynamicActivity, references.Select(a => (AssemblyReference)a).ToList());
// Compile the C# expression.
var results = new TextExpressionCompiler(settings).Compile();
if (results.HasErrors)
{
throw new Exception("Compilation failed.");
}
// attach compilation result to live activity
var compiledExpression = (ICompiledExpressionRoot)Activator.CreateInstance(results.ResultType, new object[] { dynamicActivity });
CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation(dynamicActivity, compiledExpression);
}
}
Compare to the equivalent Roslyn code - most of which is fluff that is not really needed:
public class PolicyEvaluatorGlobals
{
public Policy Policy { get; }
public PolicyEvaluatorGlobals(Policy p)
{
this.Policy = p;
}
}
internal class PolicyExpressionEvaluator
{
private readonly ScriptRunner<double> EvaluateInternal;
public PolicyExpressionEvaluator(string expression)
{
var usings = new[]
{
"System",
"System.Collections.Generic",
"System.Linq",
"System.Threading.Tasks"
};
var references = AppDomain.CurrentDomain.GetAssemblies()
.Where(a => !a.IsDynamic && !string.IsNullOrWhiteSpace(a.Location))
.ToArray();
var options = ScriptOptions.Default
.AddImports(usings)
.AddReferences(references);
this.EvaluateInternal = CSharpScript.Create<double>(expression, options, globalsType: typeof(PolicyEvaluatorGlobals))
.CreateDelegate();
}
internal double Evaluate(Policy policy)
{
return EvaluateInternal(new PolicyEvaluatorGlobals(policy)).Result;
}
}
Roslyn is fully documented, and has the helpful Scripting API Samples page with examples.

It is possible by using automapper?

I have a set of nested classes from datasource (VSO) and I would like to mapped to contracts. The point of mapping is the next:
the mapped object (contract) will have a new property, called AreaPathFull, which will have the concatenated AreaPath values of all nodes above it in the tree.
Why I want this?:
it is for displaying purposes on UI
it can be solved on UI side by dealing with javascript is pain in the bottom for me, C# much easier, might not be the best idea ever, but still...
Question:
it is possible to achieve this by using Automapper?
Unfortunately, I have almost nothing experience with Automapper and if it is not possible then I would not like to spend my time with it. If so, then I think, CustomValueResolve will be my friend.
Source:
public class Class1ToBeMapped
{
public string AreaPath = "Level1";
public List<Class1ToBeMapped> Children = new List<Class1ToBeMapped>()
{
{new Class1ToBeMapped()
{
AreaPath = "Level21",
Children = new List<Class1ToBeMapped>(){}
}},
{new Class1ToBeMapped()
{
AreaPath = "Level22",
Children = new List<Class1ToBeMapped>(){}
}}
};
}
Mapped object, desired result:
public class Class2Mapped
{
public string AreaPath = "Level1";
public string AreaPathFull = "Level1";
public List<Class2Mapped> Children = new List<Class2Mapped>()
{
{
new Class2Mapped()
{
AreaPath = "Level21",
AreaPathFull = "Level1/Level21",
Children = new List<Class2Mapped>()
{
{
new Class2Mapped()
{
AreaPath = "Level31",
AreaPathFull = "Level1/Level21/Level31",
Children = new List<Class2Mapped>()
{
{
new Class2Mapped()
{
AreaPath = "Level41",
AreaPathFull = "Level1/Level21/Level31/Level41",
Children = null
}
}
}
}
},
{
new Class2Mapped()
{
AreaPath = "Level22",
AreaPathFull = "Level1/Level22",
Children = new List<Class2Mapped>()
{
new Class2Mapped()
{
AreaPath = "Level32",
AreaPathFull = "Level1/Level22/Level32",
Children = null
}
}
}
}
}
},
}
};
}

Categories

Resources