Searching for pages with any value in property - c#

EPiServer only:
How do I search for pages with any value in a given property? I can do a search for pages with a specific value in the property, but I can't figure out how to search for "not empty".
For example, this doesn't work:
var criterias = newPropertyCriteriaCollection
{
new PropertyCriteria()
{
Condition = CompareCondition.NotEqual,
Name = "MyProperty",
IsNull = false,
Type = PropertyDataType.String,
Value = ""
}
};
var pages = DataFactory.Instance.FindPagesWithCriteria(PageReference.StartPage, criterias);
An exception is thrown, "The crieria value cannot be null or empty. Set the IsNull property to search for null."
Any ideas?

Yeah, this is confusing. In case anyone else stumbles on this, here's how to search for pages with a certain PageReference property set to something:
new PropertyCriteria()
{
createdCriteria.Name = "MyProperty";
createdCriteria.Type = PropertyDataType.PageReference;
createdCriteria.Condition = EPiServer.Filters.CompareCondition.NotEqual;
createdCriteria.Value = "0";
createdCriteria.IsNull = false;
}

Unless I'm missing a trick, this doesn't appear to be possible using the EPiServer PropertyCriteriaCollection.
I've had a dig around in reflector and here are my findings. The FPWC method eventually calls EPiServer.DataAccess.PropertySearchDB.FastFindPagesWithCriteria().
Within this method is the following:
foreach (PropertyCriteria criteria in criterias)
{
if (criteria.IsNull)
{
criteria.Value = null;
}
else if (string.IsNullOrEmpty(criteria.Value))
{
throw new EPiServerException("The crieria value cannot be null or empty. Set the IsNull property to search for null.");
}
...
}
So its not possible to search for an empty string value, without setting IsNull to true. This is then fed down to the EPiServer.DataAccess.PropertySearchDB.ExecuteCriteria method, which constructs and formats the DB command. Because IsNull is true, the netPropertySearchNull stored proc is used. Searching for a string needs to use the netPropertySearchString stored proc.
if (criteria.IsNull && !PageDB.IsMetaData(criteria.Name))
{
cmd.CommandText = "netPropertySearchNull";
}
My suggestion would be to load the full list of pages and filter using linq. Alternatively you could look into bypassing the API and implementing a direct DB query, or use some of the low level EPiServer data access methods (not recommended)
Apologies for my first answer - I really should test code before posting :)

I've seen something where the page has a a hidden bool property "Property X contains a value" that is set in the Saving event.
Then that bool property is used as a PropertyCriteria instead of the one you are REALLY interested in.

To find empty values you need to specify the IsNull property on the PropertyCriteria and use the Equal compare condition.
E.g
var criterias = newPropertyCriteriaCollection
{
new PropertyCriteria()
{
Condition = CompareCondition.NotEqual,
Name = "MyProperty",
IsNull = true,
Type = PropertyDataType.String
}
};

Related

How to fix "A value is required but not present in the request" exception?

I have a textbox, and it was designed to not accept an empty value. Means, I cannot save the form without a value in the textbox.
But now, I want to save it without a value. How to do that?
A method is called to check the value/if duplicate, that is-
public bool CheckBcodeExists(string barcode)
{
string qry = string.Format("SELECT 1 as EXIST FROM INVHITEM WHERE UPPER(ICODE) = '{0}' OR UPPER(BARCODE) = '{1}'", barcode.ToUpper(), barcode.ToUpper());
var result = _sqlexecutor.CreateSQLQuery(qry).DynamicList().FirstOrDefault();
if (result == null)
return false;
string exist = Convert.ToString(result.EXIST);
if (exist != "1")
return false;
return true;
}
Mapping of entity is
Map(x => x.Barcode).Column("BARCODE").Unique();
please guide me how to fix it
You are asking two questions.
How to fix “A value is required but not present in the request” exception?
How to allow null/empty values
For 1. You must check if the parameter has any values.
something like this.
public bool CheckBcodeExists(string barcode)
{
if (string.IsNullOrEmpty(barcode)) return false; // that'll fix your error and probably also fix your 2nd question. allowing empty values.
like everyone else said, use parameterised queries to avoid SQL injections.

Handling nonexistant JSON tokens in JSON.Net how to return default instead of throwin exception

I have a problem, under http://www.pathofexile.com/api/public-stash-tabs link there is a huge API that returns a JSON string. Many of fields in this JSON are optional, that means they only appear if there is value present.
So theoretical "Item1" can have "abyssJewel" property but
"item2" doesnt have to have "abyssJewel" property
When i try to query this JSON with JSON.Linq like this
AbyssJewel = (bool)item["abyssJewel"];
in the case of Item1 everything is good and it returns proper value
but in case of Item2 i get exception "InvalidOperationException, Cannot access child value on Newtonsoft.Json.Linq.JProperty"
I understand its because for Item2 no abyssJewel property in JSON exists so it throws exception.
My question is this, how can i handle it so that instead of throwing exception it would return a default or null value for this particular field?
I have tried playing with Activator but couldnt make anything working on my own. Any tips?
im instantiating it like this:
apiPages.Add(new Page
{
Next_Change_Id = (string)jsonObject["next_change_id"],
Stashes = jsonObject["stashes"].Select(stash => new Stash
{
AccountName = (string)stash["accountName"],
StashName = (string)stash["stash"],
StashType = (string)stash["stashType"],
Public = (bool)stash["public"],
LastCharacterName = (string)stash["lastCharacterName"],
UniqueId = (string)stash["id"],
Items = stash.Select(item => new Item
{
AbyssJewel = (bool)item["abyssJewel"],
...tl;dr...
Instead of casting directly you should try to use the TryParse() method from the Boolean class, if something goes wrong it must return false. See here
Hope it will fix your problem.

Scope of string inside lambda

I have an interesting scenario in which I've built a validation checking system that maintains a series of requirements in the form List<Tuple<Func<bool>, string>> where the Func should return true if validation failed and false otherwise. The string is a corresponding rejection description that describes the condition should the test fail.
In more simple tests like the following the validation system is quite simple:
validationChecks.Add(Tuple.Create<Func<bool>, string>(() =>
value1 == requiredValue, "value 1 did not have the required value"));
I'm struggling to understand the scope of variables within the lambda for the Func in a more advanced scenario in which the rejection string is calculated in a call to another part of the system. The scenario looks something like this:
string rejectionString = null;
validationChecks.Add(Tuple.Create<Func<bool>, string>(() => {
rejectionString = CallToAnotherMethodThatReturnsString(parameter);
if (rejectionString != null) {
return true;
} else {
return false;
}
}, rejectionString));
EDIT: As observed through testing, when this check fails the rejectionString from the Tuple is still null. I want the rejectionString that was generated by the CallToAnotherMethod to be used instead, is there any way I can do this using ref or otherwise? I need the Func's code to be able to affect the value of the string inside Item2 of the Tuple.
The problem is that the code inside of CallToAnotherMethodThatReturnsString might be code that I only want executed ONCE. However should the check fail I want to use the string that would have been returned from it as my rejection description in the Tuple. I'm unable to tell at this point what the effect of my use of rejectionString in this second example will accomplish? Will rejectionString inside the Tuple always be null? Or if CallToAnotherMethodThatReturnsString returns a different value will it be updated?
Just an idea that might work. I think if you change your second Tuple parameter to a Func that returns string instead of string value, you could come close to what you need.
string rejectionString = null;
validationChecks.Add(Tuple.Create<Func<bool>, Func<string>>(() =>
{
rejectionString = CallToAnotherMethodThatReturnsString(parameter);
if (rejectionString != null) {
return true;
} else {return false;}
},
()=>rejectionString));
In the first case your validation check would be set as
validationChecks.Add(Tuple.Create<Func<bool>, Func<string>>(() => value1 == requiredValue, ()=>"value 1 did not have the required value"));
And your validation is logic is then
if(validationChecks[0].Item1()==false)
var error = validationChecks[0].Item2();

c# copied property loses reference when referenced object is removed from list

Example
Have a look at the following code:
private void DeDuplicateOrganisations()
{
var profileOrgs = _organisations.Where(o => o.ExistsInProfile).ToList();
var kvkOrgs = _organisations.Where(o => !o.ExistsInProfile).ToList();
profileOrgs.ForEach(o =>
{
var duplicate = kvkOrgs.FirstOrDefault(k => k.KvK == o.KvK || k.Title == o.Title);
if (duplicate != null)
{
o.CompanyInfoOrganisation = duplicate.CompanyInfoOrganisation;
o.ExistsInBoth = true;
kvkOrgs.Remove(duplicate);
}
});
_organisations = profileOrgs.Concat(kvkOrgs).OrderBy(o => o.Title).ToList();
}
In this example the property CompanyInfoOrganisation (simply a get; set; property) is copied when an organisation is considered a duplicate. This all works as expected, duplicates are nicely deduplicated.
Also this is true inside this message:
_organisations.First(o => o.ExistsInBoth).CompanyInfoOrganisation != null;
Problem
Now I bind the _organisations list to a listbox
lbxCompanies.DataSource = null;
lbxCompanies.DataSource = _organisations;
lbxCompanies.DisplayMember = "Title";
lbxCompanies.SelectedIndex = -1;
and later on get the selected value:
var org = lbxCompanies.SelectedValue as Organisation;
gbxCompanyInfo.Visible = org != null;
if (gbxCompanyInfo.Visible)
if (org.CompanyInfoOrganisation != null)
// NEVER GETS HERE (but gbxComanpyInfo is visible)
If I try to read the CompanyInfoOrganisation property I always get null while I know the property was set.
Question
What is happening here? How come the property reference is destroyed? How can I prevent this from happening?
The reference you're using only has immediate scope and as soon as the query ends it exits scope and your reference disappears. So when you bind later, the reference is exactly right -- null.
profileOrgs.ForEach(o =>
{
// Right here -- var duplicate has scope ONLY within your query.
// As soon as the query is executed it leaves scope and the reference
// pointer will be null
var duplicate = kvkOrgs.FirstOrDefault(k => k.KvK == o.KvK || k.Title == o.Title);
if (duplicate != null)
{
o.CompanyInfoOrganisation = duplicate.CompanyInfoOrganisation;
o.ExistsInBoth = true;
kvkOrgs.Remove(duplicate);
}
});
Because you're using a class, you need to perform a deep MemberwiseClone on it to get a NEW copy of the object:
o.CompanyInfoOrganisation = (YourInfoType)duplicate.CompanyInfoOrganisation.MemberwiseClone();
When you load the data, load the CompanyInfoOrganisation property along with the root entity; that way it will be already loaded into memory. If using LINQ to SQL, you load via DataLoadOptions, and pass this to the context. If using Entity Framework, you use the Include method in the LINQ query.
It might have to do with capturing of variables inside the lambda. Try substituting the .ForEach to a regular foreach().
Or maybe the CompanyInfoOrganisation in duplicate was null to begin with.
The problem was I used string.Join() to show the values, and the first value to join was null (which is really annoying), resulting in an empty string, leaving me thinking the property was null. However it turned out the property was not null, but has a perfectly valid reference to the object needed. Using the debugger with a little more care would have saved me an hour or so...
Sorry!

Dynamic LINQ in c#

Hey i am making a simple search machine through alot of different coloumns in 2 tables.
I was trying to get this to abit dynamical.
I read this:
Is there a pattern using Linq to dynamically create a filter?
Which is something that really could do the trick for me.. its just in VB and i need it in c#
here is my code :
private void displayWith1Criteria(string column, string value)
{
Console.WriteLine("entering _1_ display method");
dbcontent = new DBtestEntities();
var studienummerQuery = from members in dbcontent.Medlemmer.Include("Retninger")
where column == value
orderby members.Fornavn
select new { Studienr = members.Studienummer, Fornavn = members.Fornavn, Efternavn = members.Efternavn, Email = members.Email, Studiested = members.Studiested, Betaling = members.BetalingsType, Uddannelses_Retning = members.Retninger.retningNavn };
dataGridView1.DataSource = studienummerQuery;
}
Doesn't return any data at all...
column is being called with members.Fornavn (Fornavn - a column name)
value = Anders (one of the data's in Fornavn column)
What I want to do:
My database is loaded into dbcontent using a .edmx file from ABO entity class.
My database consist of 2 tables, "Retninger" and "Medlemmer".
Medlemmer contains columns things like Fornavn(in english, Firstname), Efternavn(Lastname), Studienummer(study no.)
What i would like is a "dynamic" method that can set both which column to be searched in and the value that needs to be searched for in the set column.
When could your expression column == value possibly return true? Only if string.Equals("Fornavn", "Anders") is true.
Doing dynamic linq is hard. Is usually do it this way:
...
where (!useMycolumn1 || member.mycolumn1 == value1)
&&(!useMycolumn2 || member.mycolumn2 == value2)
&&(!useMycolumn3 || member.mycolumn3 == value3)
...
useMycolumn* is a local boolean variable which is set to true or false, depending on whether the certain condition should be tested or not. This way, unused parts of the query are optimized out at compile time.
I think this answer from Shawn Miller to the question you linked is more what you are looking for:
http://www.albahari.com/nutshell/predicatebuilder.html
Are you remembring to call the DataBind() method on the grid? How do you know nothing is being returned?
I think its because of lazy evaluation of LINQ queries.
You can try using .ToList, as below:
dataGridView1.DataSource = studienummerQuery.ToList();
also .DataBind(), if relevant for your object.
Edit:
Lazy Evaluation: This Link, would serve as a good start

Categories

Resources