I've written a custom workflow action that takes in several values, mostly using the SingleLineInput control.
When I assign literal values, I have no issues, but when I try to assign a Workflow Variable, I don't get the actual value of the variable, I get the literal text - something like {WorkflowVariable:XmlValue} - assuming my variable was names XmlValue.
I'm not sure what I could possibly be doing wrong. Any ideas?
Here's code snippets:
The javascript for retrieving the value from the SingleLineInput
function TPAWriteConfig() {
configXml.selectSingleNode("/NWActionConfig/Parameters/Parameter[#Name='FieldValue']/PrimitiveValue/#Value").text = getRTEValue('<%=fieldValue.ClientID%>');
SaveErrorHandlingSection();
return true;
}
The server control:
<Nintex:ConfigurationProperty ID="ConfigurationProperty3" runat="server" FieldTitle="Field Value" RequiredField="True">
<TemplateControlArea>
<Nintex:SingleLineInput runat="server" id="fieldValue"></Nintex:SingleLineInput>
</TemplateControlArea>
</Nintex:ConfigurationProperty>
From my adapter class:
private const string FieldValueProperty = "FieldValue";
NWActionConfig config = new NWActionConfig(this);
config.Parameters[2] = new ActivityParameter();
config.Parameters[2].Name = FieldValueProperty;
config.Parameters[2].PrimitiveValue = new PrimitiveValue();
config.Parameters[2].PrimitiveValue.Value = string.Empty;
config.Parameters[2].PrimitiveValue.ValueType = SPFieldType.Text.ToString();
From the activity class:
public static DependencyProperty FieldValueProperty = DependencyProperty.Register("FieldValue", typeof (string),
typeof (
WriteOnePdfFieldActivity));
public string FieldValue
{
get { return (string) GetValue(FieldValueProperty); }
set { SetValue(FieldValueProperty, value); }
}
I feel a little silly answering my own question, but for the sake of anyone else having the same issues. Here's how it works:
If you're putting a literal value in the field, just use the value
If you're using any other kind of assignment, do a lookup based on the value.
The code below demonstrates:
var fieldValue = FieldValue.StartsWith("{") ? ctx.AddContextDataToString(FieldValue, true) : FieldValue;
This extract the value from the workflow context. Hope this helps.
Related
I'm working on a Vue.JS project and I'm facing a strange error.
I got a WidgetDTO object filled by an axios.get request, it contains a WidgetParametersDTO object and it's defined like so:
export class WidgetParametersDTO {
[...]
public coverage: number = 0;
public colorOK: string = "";
public colorKO: string = "";
public constructor(parameters: any) {
this.coverage = parameters.coverage
this.colorOK = parameters.colorOK;
this.colorKO = parameters.colorKO;
}
}
export class WidgetDTO {
[...]
public id: string = null!;
public parameters: WidgetParametersDTO = null!;
public constructor(widgetDTO: any) {
this.id = widgetDTO.id;
this.parameters = new WidgetParametersDTO(widgetDTO.parameters);
}
When I print the full object widget.parameters, all attributes are correct, when I use widget.parameters.colorOK or widget.parameters.colorKO it works properly, but if I try to use widget.parameters.coverage, it shows 0 instead of the value printed earlier.
The type is correct (number) and I already tried several things to ensure the presence and correctness of the data, it's only acting like that when I use the attribute directly.
There's even more, I'm using npm run dev to be able to hot reload the changes as things progress. When I change some code and save, it reloads the page and prints the right value, but not when I'm hitting F5.
I tried to build the files and run the server with npm start but it didn't work.
Any advice ?
Thanks.
I have a field in my database with duplicates. I want to use it in a dropdown list, which has to return distinct data.
Here is the method that I created to do this:
public IEnumerable<SelectListItem> GetBranches(string username)
{
using (var objData = new BranchEntities())
{
IEnumerable<SelectListItem> objdataresult = objData.ABC_USER.Select(c => new SelectListItem
{
Value = c.BRANCH_CODE.ToString(),
Text = c.BRANCH_CODE
}).Distinct(new Reuseablecomp.SelectListItemComparer());
return objdataresult;
}
}
Here is the class I am using:
public static class Reuseablecomp
{
public class SelectListItemComparer : IEqualityComparer<SelectListItem>
{
public bool Equals(SelectListItem x, SelectListItem y)
{
return x.Text == y.Text && x.Value == y.Value;
}
public int GetHashCode(SelectListItem item)
{
int hashText = item.Text == null ? 0 : item.Text.GetHashCode();
int hashValue = item.Value == null ? 0 : item.Value.GetHashCode();
return hashText ^ hashValue;
}
}
}
Nothing is returned and I get the error below. When I try a basic query without Distinct, everything works fine.
{"The operation cannot be completed because the DbContext has been disposed."}
System.Exception {System.InvalidOperationException}
Inner exception = null
How can I return distinct data for my dropdown?
Technically, your problem can be solved simply by appending .ToList() after your Distinct(...) call. The problem is that queries are evaluated JIT (just in time). In other words, until the actual data the query represents is needed, the query is not actually sent to the database. Calling ToList is one such thing that requires the actual data, and therefore will cause the query to be evaluated immediately.
However, the root cause of your problem is that you are doing this within a using statement. When the method exits, the query has not yet been evaluated, but you have now disposed of your context. Therefore, when it comes time to actually evaluate that query, there's no context to do it with and you get that exception. You should really never use a database context in conjuction with using. It's just a recipe for disaster. Your context should ideally be request-scoped and you should use dependency injection to feed it to whatever objects or methods need it.
Also, for what it's worth, you can simply move your Distinct call to before your Select and you won't need a custom IEqualityComparer any more. For example:
var objdataresult = objData.ABC_USER.Distinct().Select(c => new SelectListItem
{
Value = c.BRANCH_CODE.ToString(),
Text = c.BRANCH_CODE
});
Order of ops does matter here. Calling Distinct first includes it as part of the query to the database, but calling it after, as you're doing, runs it on the in-memory collection, once evaluated. The latter requires, then, custom logic to determine what constitutes distinct items in an IEnumerable<SelectListItem>, which is obviously not necessary for the database query version.
I'm using Ektron CMS version 9.0
I have smart form content which is allocated to taxonomies e.g. I might have five smart form content items (all of same) type allocated to a taxonomy, and another three to a different taxonomy:
I need to get all content of a smart form type from a taxonomy:
public IEnumerable<T> GetListOfSmartFormFromTaxonomy<T>(long taxonomyId, bool isRecursive) where T : class
{
// TODO
}
What I have working, based on links below, is this:
public IEnumerable<TaxonomyItemData> GetListOfSmartFormFromTaxonomy(long taxonomyId)
{
TaxonomyItemCriteria criteria = new TaxonomyItemCriteria();
criteria.AddFilter(TaxonomyItemProperty.TaxonomyId, CriteriaFilterOperator.EqualTo, taxonomyId);
TaxonomyItemManager taxonomyItemManager = new TaxonomyItemManager();
List<TaxonomyItemData> taxonomyItemList = taxonomyItemManager.GetList(criteria);
return taxonomyItemList;
}
But this just gets the item's titles and ids, not the smart form data itself.
As an Ektron newbie, I don't know how to get all the items of one Smart Form type using only one call (instead of looping through each item and fetching it by ID which is not efficient)
What have I missed? I am working on this actively today and will post my findings here.
References used so far:
http://reference.ektron.com/developer/framework/Organization/TaxonomyItemManager/GetList.asp
Ektron taxonomy and library items (in v9)
EDIT
Posted my just-got-it-working solution below as an fyi and awarded closest answer as accepted. Thanks everyone for your help. Please chime in with any improvements ;)
I'd recommend using the ContentTaxonomyCriteria with the ContentManager.
long smartFormId = 42;
long taxonomyId = 127;
bool isRecursive = true;
var cm = new ContentManager();
var taxonomyCriteria = new ContentTaxonomyCriteria();
taxonomyCriteria.AddFilter(ContentProperty.XmlConfigurationId, CriteriaFilterOperator.EqualTo, smartFormId);
taxonomyCriteria.AddFilter(taxonomyId, isRecursive);
var content = cm.GetList(taxonomyCriteria);
UPDATE
The ContentData object has a property called XmlConfiguration. When the content is based on a smartform, this property will be non-null and have a positive (non-zero) Id: content[0].XmlConfiguration.Id for example.
I often add an Extension Method to my code that will tell me whether a given ContentData is based on a smart form:
public static class ContentDataExtensions
{
public static bool IsSmartFormContent(this ContentData content)
{
return content != null && content.XmlConfiguration != null && content.XmlConfiguration.Id > 0;
}
}
That way I can take a content (or list of content) and check it very quickly in code to see if it's based on a smartform or not:
foreach (var contentData in contentList)
{
if (contentData.IsSmartFormContent())
{
// Do smart-form stuff here...
}
}
Of course, if your content is coming from the framework api and you used a criteria object that is selecting based on a specific XmlConfigurationId, then in theory you wouldn't have to use that, but it still comes in handy quite often.
I'm not quite sure I understand your organizational structure, but you do have the ability to do your own sub clauses that select directly against the database.
In this case I wouldn't use the TaxonomyItemManager, I would use the ContentManager with a special criteria:
ContentManager cApi = new ContentManager();
var criteria = new ContentCriteria();
criteria.AddFilter(ContentProperty.Id, CriteriaFilterOperator.InSubClause, "select taxonomy_item_id where taxonomy_id = " + taxonomyId);
criteria.AddFilter(ContentProperty.XmlConfigurationId, CriteriaFilterOperator.EqualTo, smartformTypeId);
var yourContent = cApi.GetList(criteria);
That should do what you're asking for (grab the content specifically that is a member of a Taxonomy while only being of a specific SmartForm config). It's worth noting you don't need the second criteria piece (XmlConfigurationId) if your Taxonomy only contains that XmlConfiguration.
For Information, this is what I came up with. Noted Brian Oliver's comment on List but using patterns from other devs, can refactor later.
To clarify, we are creating classes from the XSDs generated from the smart forms, so have smart form types to play with. Your use may be simpler that ours.
public IEnumerable<T> GetListOfSmartFormFromTaxonomy<T>(long taxonomyId, bool isRecursive = false) where T : class
{
long smartFormId = GetSmartFormIdFromType(typeof(T));
// checks here for smartformid=0
ContentManager contentManager = new ContentManager();
ContentTaxonomyCriteria criteria = new ContentTaxonomyCriteria();
// Smart Form Type
criteria.AddFilter(ContentProperty.XmlConfigurationId, CriteriaFilterOperator.EqualTo, smartFormId);
// Taxonomy
criteria.AddFilter(taxonomyId, isRecursive);
List<ContentData> contentDataList = contentManager.GetList(criteria);
IEnumerable<T> smartFormList = ConvertToSmartFormList<T>(pressReleaseDataList);
return smartFormList;
}
private IEnumerable<T> ConvertToSmartFormList<T>(List<ContentData> contentDataList) where T : class
{
List<T> smartFormList = new List<T>();
if (contentDataList != null && contentDataList.Count > 0)
{
foreach (ContentData contentData in contentDataList)
{
if (contentData.IsSmartFormContent())
{
T smartForm = GetDeserializedContent<T>(contentData.Html);
if (smartForm != null)
{
PropertyInfo property = smartForm.GetType().GetProperty("ContentId");
if (property != null)
{
property.SetValue(smartForm, contentData.Id, null);
}
smartFormList.Add(smartForm);
}
}
}
}
return smartFormList;
}
private long GetSmartFormIdFromType(Type smartFormType)
{
SmartFormConfigurationManager manager = new SmartFormConfigurationManager();
SmartFormConfigurationCriteria criteria = new SmartFormConfigurationCriteria();
// Note: Smart Form Title must match the type's name, i.e. no spaces, for this to work
criteria.AddFilter(SmartFormConfigurationProperty.Title, CriteriaFilterOperator.EqualTo, smartFormType.Name);
List<SmartFormConfigurationData> configurationData = manager.GetList(criteria);
if (configurationData == null || configurationData.Count == 0)
{
return 0;
}
return configurationData.First().Id;
}
I am using Rob Conery's Massive.
The method List<DbCommand> BuildCommands(params object[] things), according to the methods comments, is supposed to take objects that "can be POCOs, Anonymous, NameValueCollections, or Expandos". But this:
var x = new { Id = new Guid("0F66CDCF-C219-4510-B81A-674CE126DD8C"), Name = "x", DisplayName = "y" };
myTable.BuildCommands(x);
Results in an InvalidCastException. Which reasonable since in the Massive.cs a cast from the passed in anonymous type to an ExpandoObject is attempted.
Why does the comment state you can pass in anything? Is there some other way to build commands from non-ExpandoObjects?
Here's some more code:
public static void ThisFails()
{
DynamicModel myTable = new DynamicModel("myConnectionString", tableName: "dbo.MyTable", primaryKeyField: "Id");
var updateMe = new { Id = new Guid("DF9A2F1B-3556-4EAC-BF2B-40E6821F3394"), Name = "abcx", DisplayName = "x" };
var commands = myTable.BuildCommands(updateMe); // This fails
myTable.Execute(commands);
}
public static void ThisSucceeds()
{
DynamicModel myTable = new DynamicModel("myConnectionString", tableName: "dbo.MyTable", primaryKeyField: "Id");
dynamic updateMe = new ExpandoObject();
updateMe.Id = new Guid("DF9A2F1B-3556-4EAC-BF2B-40E6821F3394");
updateMe.Name = "abcx";
updateMe.DisplayName = "x";
var commands = myTable.BuildCommands(updateMe);
myTable.Execute(commands);
}
The code that fails results in:
Unable to cast object of type
'<>f__AnonymousType03[System.Guid,System.String,System.String]' to
type <br/>
'System.Collections.Generic.IDictionary2[System.String,System.Object]'.
It's thrown from the first line in your method
public virtual DbCommand CreateUpdateCommand(dynamic expando, object key)
{
var settings = (IDictionary<string, object>)expando;
...
To me it looks like there should be a call to your extension method ToExpando before CreateUpdateCommand is called?
I think this is why people make methods private and public :). You're not supposed to call BuildCommands directly (though the code you have here still should work). I have a feeling there might be a bug that was committed in a patch.
That said - I believe this will work if you call myTable.Update() or myTable.Insert().
This last part answers the question - in terms of a possible "issue" - let's take that to Github.
This is not a question but my answer to a problem I could not find a solution to on the internet.
I had a problem clearing the SearchText in an MVVM Silverlight application. I could clear clear the SelectedItem and Text but the SearchText was left behind. It is read only and cannot be changed by binding.
Example: AutoCompleteBox with a list of Countries. When the user wants to enter Australia they enter 'au' at this point the list appers with Austria and Australia. The user can then select Australia and move on. At the end of editing they click on a 'Save' button. At this point it is likely that you would want to clear the data forn for entering new data.
Even if you have bindings to the SelectedItem and the Text properties and you set them to 'null' and string.Empty respectively the SearchText property remains and the AutoCompleteBox will not clear but will contain 'au'.
I posted about this all over the internet but could get no answer on the control itself and so I came at it from a different angle which may help someone who ends up frustrated like me.
I am using a Silverlight Navigation template application which uses a NavigationFrame in which to load Silverlight pages. I noticed that if I navigated to another page and returned to my data form the SearchText was cleared. Any values that were bound to properties remained valid, just the SearchText had cleared on all AutoCompleteBoxes. I therefore used the PageConductor method of injecting the NavigationFrame into the ViewModel where I could call the refresh method. I got this method from John Papa's example from the Silverlight Firestarter event , I simply added a Refresh method to the IPageConductor interface so I am now able to call 'PageConductor.Refresh()' which is like reloading the page. I hope this helps someone out there.
var t = ProductCombo.ItemsSource;
ProductCombo.ItemsSource = null;
ProductCombo.Text = string.Empty;
ProductCombo.SelectedValue = null;
//ProductCombo.Text = string.Empty;
ProductCombo.ItemsSource = t;
Try this please.it worked for me
You must clear the property bindeaded to Text inside set part of SelectedItem Binded property, like this:
public string AnalisisText
{
get { return _analisisText; }
set
{
if (_analisisText == value)
{
return;
}
_analisisText = value;
RaisePropertyChanged(AnalisisTextPropertyName);
}
}
public DatosAutoCompletaPedidosDetalleViewDTO AnalisisSelect
{
get { return _analisisSelect; }
set
{
if (_analisisSelect == value)
{
return;
}
_analisisSelect = value;
if (_analisisSelect == null) AnalisisText = "";
RaisePropertyChanged(AnalisisSelectPropertyName);
}
}
So, when you set null to property SelectedItem , the other property will set to "".
The easiest way I've found is to extend the AutoCompleteBox:
public class AutoCompleteBoxClear : AutoCompleteBox
{
public AutoCompleteBoxClear()
{
DataContextChanged += (o, e) =>
{
if (SelectedItem == null)
Text = string.Empty;
};
}
}
Now use your new AutoCompleteBoxClear control in your XAML.
This clears the text only when autocompletebox datacontext changes to null (ie the user clicks add in the dataform.)
Note: I think DataContextChanged is available only in Silverlight 5, but I'd guess that anyone still using Silverlight these days would likely have upgraded by now...
var t = ProductCombo.ItemsSource;
ProductCombo.ItemsSource = null;
ProductCombo.Text = string.Empty;
ProductCombo.SelectedValue = null;
//ProductCombo.Text = string.Empty;
ProductCombo.ItemsSource = t;
Unfotunately this is code-behind and I needed an MVVM solution.
I recently had the same problem with my WPF app. I found out that the solution is not to set the object bound to SelectedItem to null, but to its default value. Took me a while to figure this out. So in your example, it would not be SelectedCountry = null, but SelectedCountry = new SelectedCountry(). In this case the SearchText is cleared also. Check my SO post regarding this matter: Autocompletebox doesn't clear keyboard strokes.
Sure SearchText property is read-only, but we can get the child component of AutoCompleteBox:
var searchText = autoCompBox.GetChildByType<TextBox>(item => item.Name == "Text");
And now we can reset SearchText via Text property of TextBox-component:
if (searchText != null) searchText.Text = string.Empty;
In C# 6.0 it is more laconically:
autoCompBox.GetChildByType<TextBox>(item => item.Name == "Text")?.Text = string.Empty;