Set Search Property Value to a Variable - c#

I have a control which is a TreeView node that will always be set to the name of the PC you're currently running the tested software on. Therefore I need the Search Property for the control's Name property to be set to `Environment.MachineName like so:
The problem with this is that inside UIMap.Designer.cs I can see the generated code that this makes and it's trying to use Environment.MachineName as a string:
this.SearchProperties[WinTreeItem.PropertyNames.Name] = "Environment.MachineName";
Obviously this approach won't work, and it's not possible to manually edit UIMap.Designer.cs to change this. How can I make this work then?

The general approach is to use the UI Map editor to remove that search item. This should be possible from the window shown in the question. Then, in the test method that needs to do the search, add a statement something like
this.uimap.controlNames.SearchProperties[WinTreeItem.PropertyNames.Name]
= Environment.MachineName;
or
this.uimap.controlNames.SearchProperties.Add(name, Environment.MachineName;
The precise statement depends on the structure of the controls, so where I wrote .controlNames. it may need a series of dot-separated control names.

Related

Sitecore Custom Rules

I have a custom rule in Sitecore:
where person's status is [condition,Tree,root=/sitecore/content/Home/PersonStates, specified state]
I want to replace the hard coded path with one that points to any folder that has it's template id matching the one I specified. This is because the author will create these values (of a specific template in the root folder).
I have tried this and it does not work:
where person's status is [condition,Tree,root=query:/sitecore/content/Common/Categories/*[##templateid='{3B0461BF-9ABC-4AF1-B937-C8D225FC2313}'], specified state]
Furthermore, I need to restrict some of these values based on properties that these items would have.
Eg: The author adds 5 states. I need only those states which have the active flag set to true.
How would I do this?
Out of the box the Tree Macro does not support this, the solution is to create a custom Macro that allows a query to be executed. In order to do this you will have to implement IRuleMacro and implement your logic. Make sure to URL encode your query. Also note that the macro does not have any context when called, so you will have to implement this yourself. An example of this can be found here

MySQL variable setting through connection string or connection object?

This is a contrived example however I have simplified it for ease of explanation.
Please see my update at the bottom before investing too much of your
time!
Background
I have some (a lot of) code that ordinarily queries my DB as follows:
SELECT name FROM sites where IsLive=1;
My challenge is to, under certain conditions, return the full list of sites, essentially
SELECT name from sites;
I do not wish to modify the actual C# code issuing the SQL (although I can do if I have to in order to achieve my goal which is purely for demonstration purposes).
Therefore in order to leave as much untouched as possible my thoughts are to insert a database-proxy-view called site that returns the data dependent on a control variable
Method
Rename existing site table to site_table
Create a new view named site that the C# code now unknowingly targets and which returns the (possibly filtered) details from site_table according to the control variable value (Note a limitation on variables in views meant I had to create a function in order to demonstrate this - see http://dev.mysql.com/doc/refman/5.7/en/create-view.html wrt error 1351)
Changes made
ALTER TABLE site RENAME TO site_table;
CREATE FUNCTION controlVariableFn() RETURNS VARCHAR(16) RETURN #controlVariable;
CREATE OR REPLACE VIEW site AS SELECT * from site_table WHERE (IsLive = 1 OR controlVariableFn() = 'SHOWALL');
The above statements are ugly but achieve the result I want, however my problem is to dynamically pass through controlVariable without changing my main SQL queries being sent.
My Question
Is there a way to (ideally as I am creating my connection object) define the controlVariable outside the actual SQL to be executed but which the View can still access similar to the above as though it had been supplied as a regular user variable parameter to the query?
so the code would look something like
var connectionString = "Server=localhost;User ID=un;Password=pw;Database=dbname;....";
DbConnection db = new MySql.Data.MySqlClient.MySqlConnection
(connectionString, "controlVariable=SHOWALL");
var results = db.Query<Site>("SELECT * FROM site;");
(I understand that this would not be a smart permanent solution)
Update
My preferred solution as outlined above will not work for me as once I get into my data access layer as the results set will
essentially be filtered again back to the original set. There are some circumstances where it
could work; it would depend on the SQL issued (e.g. when collapsing a
results set down instead of trying to expand a results set as I was
trying to do here).
In that regard I am no longer looking for an answer here but will leave it for posterity as a preferred option and as per the guidelines - thanks anyway.
If you do not want to edit the c# code then the variable will have to be stored in the database although i am not sure how you will not edit the code.
If you are willing to edit the code then you can access a secondary configuration table which will have the settings that you would like the user to pass to the view. take this and allow the user to select which they want and then pass it to the view through the application.

How to write a Wix Custom Action to Read XML data and set Properties

I have been working on this for days and I just don't get the concept of how Custom Actions work with Wix. Or at least I don't see how to do what I want.
I have several XML files that I want to read a value from and populate a property that gets displayed in a UI Dialog. Then when the install begins update that value in another XML file.
I need to be able to pass the filename including path of the local XML file and the node to search for and the key value pair to extract. I also need to pass what property needs to be updated.
I understand the CustomAction DLL concept. And that the session.CustomActionData["parametername"] syntax for passing in parameters. And the session["property"] = to set a property.
But I can't figure out the syntax of the wsx code to make it all happen. I read different examples doing it different ways?
I searched all the Google links out there an nothing seems to fit what I want to do?
You want this to be an immediate custom action not a deferred custom action so CustomActionData has no relevance to you.
What I would do is write a custom table like such:
Id [PK]
File (Formatted)
XPATH
Property
Here's an example:
mySearch
[SOMEPROPERTY]
/test[#'test'] (something like that, I hate xpath)
MYPROPERTY
You can use things like Property/FileSearch to have MSI's AppSearch resolve the location of a file and assign it to [SOMEPROPERTY]. Then you write a custom action scheduled after AppSearch to fetch this table's data, iterate it and fetch the attribute value (or element innertext) of each row and assign it to MYPROPERTY.
InstallShield gave this to me for free. I don't think WiX has a built in extension to do this. Maybe there is a community extension out there. It would probably take me an hour to write a prototype of this in C#/DTF.

How to solve cast issues in ValidationRule classes' properties?

I need to create a few tests for the user roles in a web application. To minimize the description, one of the tests involves checking if a menu entry is displayed or not for an user.
For this test, I use a table called UserRoles, that looks like this:
sUserName bDoesntHaveMenuX
User1 1
User2 0
User3 1
bDoesntHaveMenuX is of type bit.
I have a class derived from ValidationRule that checks if a certain text is present in a page, based on a XPath expression to locate the node where to look for the text.
The public properties of this class are:
string XPathExpression
string Text
bool FailIfFound
The last one dictates if the rule should fail if the text is found or not found.
In the test I added a datasource for the table mentioned in the beginning, called DS.
For the request I'm interested in I added a new instance of my validation rule class, with the following values:
Text=MenuX
XPathExpression=//div[#id='menu']//td
FailIfFound={{DS.UserRoles.bDoesntHaveMenuX}}
Unfortunately, this doesn't work.
The reason seems to be that the data binding process creates a context variable
DS.UserRoles.bDoesntHaveMenuX has the value "False" or "True". The value is a string, so the binding results in a casting error.
My options, as far as I can think of, are:
Change the validation rule to accept strings for FailIfFound. Not a valid
option, for 2 reasons: it's a hack and the same rule is used in
other places.
Make a new validation rule that will use the above mentioned one,
and implement the FailIfFound as string. I also don't like this, for
the same reason as above. It's a hack.
Make the test coded and do the proper cast before passing the data
to the validation rule. I don't like this one because I prefer to
have the test as coded only if there is no other way.
Which brings me to the question. Is there another way?
Thank you.
So the fundamental issue is that you have no control over how the data-binding treats the 'bit' data type, and it's getting converted to string instead of bool.
The only solution I can think of (which is sadly still a bit of a hack, but not so egregious as changing FailIfFound to string) is to create a WebTestPlugin, and in the PreRequestDataBinding or PreRequest event, convert the value from string to bool. Don't forget to add the plugin to your test(s) (easy mistake I have made).
Then when the validation rule is created it should pick up the nice new bool value and work correctly.
e.g.
string val = e.WebTest.Context["DS.UserRoles.bDoesntHaveMenuX"].ToString();
e.WebTest.Context["DS.UserRoles.bDoesntHaveMenuX"] = (val == "True");
I didn't actually try this... hope it works.
EDIT: round two... a better solution
Change the FailIfFound property to string (in a subclass as you mentioned), so it can work properly with data-binding.
Implement a TypeConverter that provides a dropdown list of valid values for the property in the rule's PropertyGrid (True, False), so in the GUI it looks identical to the rule having FailIfFound as a bool. You can still type your own value into the box when necessary (e.g. for data-binding).
Add the path of the .dll containing the TypeConverter code to your test project's References section.
This is what I have started doing and it is much more satisfying than having to type 'True' or 'False' in the property's edit box.

Referring To Named Elements Created Programmatically?

I have a RichTextBox created programmatically with the following code:
RichTextBox RT = new RichTextBox();
RT.Name = "asdf";
RT.Text = "blah";
TableLayoutPanel.Controls.Add(RT,0,0);
Now let's say I want to modify the text of RT, and it's name is "asdf", Visual Studio won't allow me to write asdf.Text = "haha" because asdf doesn't exist yet.
How can I grab "asdf" specifically and set its text? Because this RichTextBox is in a specific cell, can I grab it based on its cell coordinates?
You should be able to get a reference to it via the TableLayoutPanel.Controls property, which returns a TableLayoutControlCollection. That class provides two ways to locate a control by name: the Item property and the Find method. The Item property returns a control with the specified name, whereas the Find method returns a collection of controls. In both cases you would need to cast from a Control to a RichTextBox.
var rt = (RichTextBox)myTableLayoutPanel.Controls.Item["asdf"];
// or
var rts = myTableLayoutPanel.Controls.Find("asdf", false);
foreach (var rt in rts)
// (RichTextBox)rt ...
EDIT: be sure to check that the result is not null before using it in case the control is not found.
Well... you did instantiate the RichTextBox and have a reference that you can use; it's called "RT" in your example.
Now, likely you've done this in a method so it was locally scoped and is no longer available when you want it. So you save that reference somehow by assigning it to some member you can access. If you have a lot of them and want to differentiate by name somehow, you might stick it into a Dictionary<string, RichTextBox>, for example. Or you could put it in some static variable; there are numerous options, each with their own pros and cons.
The one thing you probably don't want to do is walk the control tree looking for the control with the name you specified. But you could also do that, if you really wanted to.

Categories

Resources