BoldReports - ReportHelper.GetParametersWithValues() returns parameter collection with empty values - reportviewer

BoldReports ReportViewer Controller:
I'm using the ReportHelper.GetParametersWithValues() function in the OnReportLoaded() method to retrieve the report parameters. It is successfully retrieving the list of parameters, however, only the name attributes are populated - the values are null.
private ReportParameterInfoCollection _rptParamColl;
public void OnReportLoaded(ReportViewerOptions reportOption)
{
_rptParamColl = ReportHelper.GetParametersWithValues(jsonArray, this, _cache);
if (_rptParamColl != null)
{
foreach (ReportParameterInfo rptParam in _rptParamColl)
{
if (rptParam.Name == "OrgID")
{
if (rptParam.Values != null )
{
// perform appropriate validation on rptParam.Values[0]
}
}
}
}
}
In the code sample above, rptParam.Name has a value, but the rptParam.Values is null. I know the values exist, as when I inspect the jsonArray object, they are in there (although oddly, after calling ReportHelper.GetParametersWithValues(), the jsonArray object is cleared? Same also happens when calling ReportHelper.GetDataSources(). This is also a problem, as I want to call both methods, and after calling one, cannot call the other... )
Any ideas what I may be doing wrong?

Using the PostReportAction method you can get the client-side parameter value. Please refer to the below code snippet,
public object PostReportAction([FromBody] Dictionary<string, object> jsonResult)
{
if (jsonResult.ContainsKey("parameters") && jsonResult["parameters"] != null)
{
var parameterValues = Newtonsoft.Json.JsonConvert.DeserializeObject<BoldReports.Web.ReportParameterInfoCollection>(jsonResult["parameters"].ToString());
}
return ReportHelper.ProcessReport(jsonResult, this, this._cache);
}

Related

I am trying to implement multiGet operation in Spring on Redis, it throws me an error

I am trying to execute multiGet function in Spring on Redis. It throws me an error. I have implemented get function successfully but while implementing multiGet it asks me for a Collection as second parameter. I am not sure what to enter? Can someone please guide me here.
Here is my code for multiGet()
Method definition:
#Override
public User findById_MultiGet(String id) {
return (User)hashOperations.multiGet("USER", id);
}
Code In Controller :
#GetMapping("Map/MultiGet/{id}")
public User allMultiGet(#PathVariable("id") final String id) {
// MultiGet function
return userRepository.findById_MultiGet(id);
}
Error for above multiget method is multiget(Object, Collection) type not (String,String) type
Below code for Get function is working.
public User findById(String id) {
return (User)hashOperations.get("USER", id);
}
Code In Controller for Get function :
#GetMapping("Map/Get/{id}")
public User allGet(#PathVariable("id") final String id) {
// Get function
return userRepository.findById(id);
}
For multiGet the second parameter should be a Collection like a List (in case you want the values of the list returned as result on the same positions as their belonging keys in the input list) or a Set.
In your example this would be something like this:
List<Object> values = hashOperations.multiGet("USER", Arrays.asList("id", "name"));
Object id = values.get(0);
Object name = values.get(1);

Callee taking action based on type of caller

I would like to know if there is some alternate better pattern other than below where an object passes itself as a context to another object which in turn uses the context or lack as logic to build the necessary output. I have tried making the caller/sender an interface and pass itself as an interface but the real question is is it good practice for the called object to even know who its caller is, i.e. to distinguish it from other callers and take separate actions if necessary? Am I missing a piece to the puzzle?
Caller (CGQuery):
public string RenderForLoop()
{
...
sb.Append(string.Join("",this.ContentIsCGExpressions.Select(exp => exp.GetProcessedExpression(this))));
...
Callee (CGExpression):
public string GetProcessedExpression(object context = null)
{
...
retv = ReplaceCodes(retv, context);
...
private string ReplaceCodes(string retv, object context = null)
{
... retv = ReplaceContextSequenceCode(retv, context);
return retv;
}
...
private string ReplaceContextSequenceCode(string retv, object context = null)
{
var _regx = new Regex("(?i)<q_ctx_seq>");
var _matchresult = _regx.Match(retv);
while (_matchresult.Success)
{
string replacement = FetchContextSequenceQueryTableFieldExpression(context);
retv = retv.Replace(_matchresult.Groups[0].Value, replacement);
_matchresult = _matchresult.NextMatch();
}
return retv;
}
private string FetchContextSequenceQueryTableFieldExpression(object context = null)
{
if (context != null && context is CGQuery)
{
return ((CGQuery)context).FetchContextSequenceQueryTableFieldExpression();
}
return this.CGStatementsUsedAsParamsFor.Any() ?
this.CGStatementsUsedAsParamsFor.Single().FetchContextSequenceQueryTableFieldExpression(context)
:
this.CGQueriesContentFor.Single().FetchContextSequenceQueryTableFieldExpression();
}
It's this line in the above that I'm concerned about (seems to violate encapsulation?)
if (context != null && context is CGQuery)
{
return ((CGQuery)context).FetchContextSequenceQueryTableFieldExpression();
}
sorry I don't know how to highlight the code in the main block.
What about letting the caller deliver an object to the callee containing the action to execute? The caller may be queried within this action without the callee being aware of its existence.
Generally I would say it's not good OOP practice to decide behaviour on the class of the calling object.

Mono.CSharp: how do I inject a value/entity *into* a script?

Just came across the latest build of Mono.CSharp and love the promise it offers.
Was able to get the following all worked out:
namespace XAct.Spikes.Duo
{
class Program
{
static void Main(string[] args)
{
CompilerSettings compilerSettings = new CompilerSettings();
compilerSettings.LoadDefaultReferences = true;
Report report = new Report(new Mono.CSharp.ConsoleReportPrinter());
Mono.CSharp.Evaluator e;
e= new Evaluator(compilerSettings, report);
//IMPORTANT:This has to be put before you include references to any assemblies
//our you;ll get a stream of errors:
e.Run("using System;");
//IMPORTANT:You have to reference the assemblies your code references...
//...including this one:
e.Run("using XAct.Spikes.Duo;");
//Go crazy -- although that takes time:
//foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
//{
// e.ReferenceAssembly(assembly);
//}
//More appropriate in most cases:
e.ReferenceAssembly((typeof(A).Assembly));
//Exception due to no semicolon
//e.Run("var a = 1+3");
//Doesn't set anything:
//e.Run("a = 1+3;");
//Works:
//e.ReferenceAssembly(typeof(A).Assembly);
e.Run("var a = 1+3;");
e.Run("A x = new A{Name=\"Joe\"};");
var a = e.Evaluate("a;");
var x = e.Evaluate("x;");
//Not extremely useful:
string check = e.GetVars();
//Note that you have to type it:
Console.WriteLine(((A) x).Name);
e = new Evaluator(compilerSettings, report);
var b = e.Evaluate("a;");
}
}
public class A
{
public string Name { get; set; }
}
}
And that was fun...can create a variable in the script's scope, and export the value.
There's just one last thing to figure out... how can I get a value in (eg, a domain entity that I want to apply a Rule script on), without using a static (am thinking of using this in a web app)?
I've seen the use compiled delegates -- but that was for the previous version of Mono.CSharp, and it doesn't seem to work any longer.
Anybody have a suggestion on how to do this with the current version?
Thanks very much.
References:
* Injecting a variable into the Mono.CSharp.Evaluator (runtime compiling a LINQ query from string)
* http://naveensrinivasan.com/tag/mono/
I know it's almost 9 years later, but I think I found a viable solution to inject local variables. It is using a static variable but can still be used by multiple evaluators without collision.
You can use a static Dictionary<string, object> which holds the reference to be injected. Let's say we are doing all this from within our class CsharpConsole:
public class CsharpConsole {
public static Dictionary<string, object> InjectionRepository {get; set; } = new Dictionary<string, object>();
}
The idea is to temporarily place the value in there with a GUID as key so there won't be any conflict between multiple evaluator instances. To inject do this:
public void InjectLocal(string name, object value, string type=null) {
var id = Guid.NewGuid().ToString();
InjectionRepository[id] = value;
type = type ?? value.GetType().FullName;
// note for generic or nested types value.GetType().FullName won't return a compilable type string, so you have to set the type parameter manually
var success = _evaluator.Run($"var {name} = ({type})MyNamespace.CsharpConsole.InjectionRepository[\"{id}\"];");
// clean it up to avoid memory leak
InjectionRepository.Remove(id);
}
Also for accessing local variables there is a workaround using Reflection so you can have a nice [] accessor with get and set:
public object this[string variable]
{
get
{
FieldInfo fieldInfo = typeof(Evaluator).GetField("fields", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldInfo != null)
{
var fields = fieldInfo.GetValue(_evaluator) as Dictionary<string, Tuple<FieldSpec, FieldInfo>>;
if (fields != null)
{
if (fields.TryGetValue(variable, out var tuple) && tuple != null)
{
var value = tuple.Item2.GetValue(_evaluator);
return value;
}
}
}
return null;
}
set
{
InjectLocal(variable, value);
}
}
Using this trick, you can even inject delegates and functions that your evaluated code can call from within the script. For instance, I inject a print function which my code can call to ouput something to the gui console window:
public delegate void PrintFunc(params object[] o);
public void puts(params object[] o)
{
// call the OnPrint event to redirect the output to gui console
if (OnPrint!=null)
OnPrint(string.Join("", o.Select(x => (x ?? "null").ToString() + "\n").ToArray()));
}
This puts function can now be easily injected like this:
InjectLocal("puts", (PrintFunc)puts, "CsInterpreter2.PrintFunc");
And just be called from within your scripts:
puts(new object[] { "hello", "world!" });
Note, there is also a native function print but it directly writes to STDOUT and redirecting individual output from multiple console windows is not possible.

Generate parameter list with userdefined types at runtime (using C#)

As part of my project, I am trying to build a web UI where user will select a method and pass the values. My program should be able to call the method dynamically and build a parameter list on runtime to pass it to the method.
I have created a comma separated list (string) of key and value pairs. This key/value pair is nothing but the parameter name and value of my method (methodname stored in a variable). Example: string params = "ID:123;Name:Garry;Address:addressObject;AddressLine:108 Plaza Lane;City:Avenel;State:NJ;Zip:07001;". Where ID and Name are simple string varaibles while Address is user defined type. What follows after Address i.e. AddressLine, City, State and Zip is elements of Address object. And my method definition is
public string GetInfo(string ID, string Name, Address addressObject)
{
//return something;
}
I am dynamically calling the method (GetInfo) that is stored in sMethodName variable using DynamicProxy like :
string sMethodName = "GetInfo";
object result = (object) proxy.CallMethod(sMethodName, arguments);
Challenge is how to pass the argument list dynamically? Till now I am just able to extract the values from the csv variable into NamedValueCollection. Here is the code:
public static void StoreParameterValues(string param)
{
nvc = new NameValueCollection();
param = param.TrimEnd(';');
string[] parameters = param.Split(new char[] { ';' });
foreach (string val in parameters)
{
string[] keyValue = val.Split(new char[] { ':' });
nvc.Add(keyValue[0], keyValue[1]);
}
}
..and here is the code that tries to build the parameter:
string methodName = "GetInfo";
DynamicProxyFactory factory = new DynamicProxyFactory("http://../myservice.svc");
string sContract = "";
foreach (ServiceEndpoint endpoint in factory.Endpoints)
{
sContract = endpoint.Contract.Name;
}
DynamicProxy proxy = factory.CreateProxy(sContract);
string[] values = null;
// Create the parameter list
object[] arguments = new object[nvc.Count];
int i = -1;
foreach (string key in nvc.Keys)
{
values = nvc.GetValues(key);
foreach (string value in values)
{
arguments[++i] = value;
}
}
object result = (object) proxy.CallMethod(methodName, arguments);
The above code works if I have simple primitive types but not sure how can I build the logic for any other userdefined types. How can I create a object dynamically of type stored in a variable? Not sure if I was able to put my question correctly. I hope so :)
Edit: 01/19/2011: Applied the suggestion from Chris - using Reflection instead of ComponentModel.
I have converted the code to make it more generic. This works now for all primitive and custom types (resursion). Code snippet below:
private object BuildParameterList(Type type)
{
object item = new object();
item = Activator.CreateInstance(type);
PropertyInfo[] propArray = type.GetProperties(BindingFlags.Public|BindingFlags.Instance);
for (int i = 0; i < propArray.Length; i++)
{
PropertyInfo pi = (PropertyInfo)propArray[i];
////Check for custom type
if (IsCustomType(pi.PropertyType))
{
object item1 = BuildParameterList(pi.PropertyType);
pi.SetValue(item, item1, null);
}
else
{
if (property.ContainsKey(pi.Name))
{
pi.SetValue(item, Convert.ChangeType(property[pi.Name], pi.PropertyType), null);
}
}
}
return item;
}
But if one of the property is Color (I just tested with Color type, will fail with other system types aswell-i guess), then it fails at the following line. Not sure how to handle system types - Color or something similar.
pi.SetValue(item, Convert.ChangeType(property[pi.Name], pi.PropertyType), null);
Can you not find what types are expected by the method, by inspecting its ParameterInfos:
endpoint.Contract.ContractType.GetMethod(methodName).GetParameters();
and then instantiating the custom types using:
Activator.CreateInstance(parameterType);

Parameters or Arguments in WCF service

A wcf service accessing an SQL database:
private void GetImagesDataFromDB(int imageIndex, int **extraParam**)
{
ServiceReference1.DbServiceClient webService =
new ServiceReference1.DbServiceClient();
webService.GetSeriesImagesCompleted += new EventHandler<ServiceReference1.GetSeriesImagesCompletedEventArgs>(webService_GetSeriesImagesCompleted);
webService.GetSeriesImagesAsync(imageIndex);
}
the GetImageSeriesCompleted EventHandler is here:
void webService_GetSeriesImagesCompleted(object sender,
TheApp.ServiceReference1.GetSeriesImagesCompletedEventArgs e)
{
if (e.Result != null)
{
if (**extraParam** == 1)
{
lstImages = e.Result.ToList();
}
else
{
// do something else
}
}
}
The service itself is like this:
public List<Image> GetSeriesImages(int SeriesId)
{
DataClassDataContext db = new DataClassDataContext();
var images = from s in db.Images
where s.SeriesID == SeriesId
select s;
return images.ToList();
}
What is the best way to pass the extraParam to the service completed EventHandler? I need this to direct my service return to a proper UI control.
Thanks.
You've probably figured this out by now, but the webService.GetSeriesImagesAsync() call has a second overload, namely, webService.GetSeriesImagesAsync(int seriesId, object userState). That second parameter will get passed into the callback as e.UserState. A good pattern is actually to pass a lambda callback as the userstate, and execute that in the webService_GetSeriesImagesCompleted() method.