Call function who's name is stored in a variable - c#

I have created a small classic asp file that I indend to call form asp.net using the below. I works, but it feels wrong somehow:
Booking.BelongsToSite = file_get_contents("http://localhost:82/test2.asp?functionName=RetBTS&param=" + User.ID);
protected string file_get_contents(string fileName)
{
string sContents = string.Empty;
if (fileName.ToLower().IndexOf("http:") > -1)
{ // URL
System.Net.WebClient wc = new System.Net.WebClient();
byte[] response = wc.DownloadData(fileName);
sContents = System.Text.Encoding.ASCII.GetString(response);
}
else
{
// Regular Filename
System.IO.StreamReader sr = new System.IO.StreamReader(fileName);
sContents = sr.ReadToEnd();
sr.Close();
}
return sContents;
}
Can anyone see any problems with doing this?
Also is it possible to do something like the below in Classic ASP / VB script. I can't get it to call a dynamic function name:
dim functionName, param, result
functionName = request("functionName")
param = request("param")
result = functionName(param)
Also any idea how to parse the parameters. Say if I pass the parameters in the head like "1,2,3,4", how can I pass the into the parenthesis?

I think you're looking for the Eval function in VBScript. You can use it to call your method in the following way (demo script is vbs in wsh):
Dim func, param
func = "Hello"
param = "everybody"
MsgBox(Eval(func & "(""" & param & """)"))
Function Hello(name)
Hello = "Hello " & name
End Function
That returns "Hello everybody", as expected.
As for your asp.net code: I'm not going to judge whether or not your solution is sensible, I don't know the situation. It can definitely work though. Just two remarks:
Both WebClient and StreamReader implement IDisposable. Wrap them in a using block.
If you're going to download urls like that, make sure to validate your string, so that you don't go and download bad urls. Same for the function name in your classic asp that you pass in your querystring.
Menno

Try to use GetRef instead of Eval.
dim functionName, param, result
functionName = request("functionName")
param = request("param")
result = GetRef(functionName)(param)

Related

Call a python function with named parameter using python.net from a C# code

I want to call a python function from C# code. To do that, I used Python for .NET to call function as shown in the following lines of code
using System;
using Python.Runtime;
public class Test{
public static void Main(){
using(Py.GIL()){
dynamic lb = Py.Import("lb");
dynamic result = lb.analyze("SomeValue");
Console.WriteLine(result);
}
}
}
The python function is something like this:
def analyze(source, printout = False, raw = True):
# removed for bravity
So the question is, how can I set "raw" to False when I call the analyze function from C# code. I tried the following but it didn't work.
1. dynamic result = lb.analyze("SomeSource", raw : false); // No result
2. dynamic result = lb.analyze("SomeSource", #"raw = False"); // No result
I know it is easy to do by doing this:
dynamic result = lb.analyze("SomeSource", False, False);
But what if there is more than six or seven named parameter, it would not be great to insert it all manually and change the one I wanted. For example, the python library that I am using have 12 named parameter with default value including two more parameters with no default value.
UPDATED
I also tried:
3. dynamic result = lb.analyze("SomeSource", raw = false); // C# compilation error
To apply keyword arguments use:
lb.analyze("SomeSource", Py.kw("raw", false));
See readme.
Another approach is using C# keyword argument syntax that was recently added to pythonnet:
lb.analyze("SomeSource", raw: false);
Since I am using one function to call python scripts I have used a Listto hold the parameter values. I am also passing in a class name and function name since my python scripts contain multiple classes with multiple functions. I don't use the 'self' parameter in any of my classes, so they are static functions. I am providing a snippet of my code to help you and anyone else out that is using python in .net. I personally use it for communciation with USB.
Here is an example of one of my callers. Ignore the function name but look at how it's calls the ExecuteScript and passing int he parameterset. Notice the list is of type object, incase your paramters are a mix of string/int/bool/objects etc.
public string SendCommand(string comport, string command)
{
try
{
List<object> parameterSet = new() { comport, command };
string result = _pythonService.ExecuteScript<string>("usb", "usb", "sendCommand", parameterSet);
return result;
}
catch (Exception)
{
throw;
}
}
Here is a function that executes the class function
public dynamic? ExecuteScript<T>(string scriptFile, string className, string functionName, List<object> paramset)
{
T? result = default;
try
{
// Location of all the python scripts in the project. lets get the python file we are specifying in the function param
string file = $"{Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)}\\PythonScripts\\{scriptFile}.py";
// This is initalized in the program.cs, but just want to make sure it's initialized in case something happens
if (!PythonEngine.IsInitialized)
{
PythonEngine.Initialize();
Py.GIL();
}
using (var scope = Py.CreateScope())
{
PyObject? pythonReturn; // Our returned PythonObject from the python function call
string code = File.ReadAllText(file); // Get the python file as raw text
var scriptCompiled = PythonEngine.Compile(code, file); // Compile the code/file
scope.Execute(scriptCompiled); // Execute the compiled python so we can start calling it.
PyObject pythonClass = scope.Get(className); // Lets get an instance of the class in python
// Add parameters to the function?
if (paramset != null && paramset.Count > 0)
{
PyObject[] pyParams = new PyObject[paramset.Count]; // This is an array of python parameters passed into a function
// Loop through our incoming c# list of parameters and create PythonObject array .
for (int i = 0; i < paramset.Count; i++)
{
pyParams[i] = paramset[i].ToPython();
}
pythonReturn = pythonClass.InvokeMethod(functionName, pyParams); // Call the function on the class with parameters
}
else // We aren't using parameters here
pythonReturn = pythonClass.InvokeMethod(functionName); // Call the function on the class
// Lets convert our returned pythonObject to that of the object type (C#)
object? netObject = pythonReturn.AsManagedObject(typeof(object));
// A special case of when we want a list back. We will convert the object to the specific type in the caller function
if (typeof(T) == typeof(IList<object>))
{
object[] something = pythonReturn.As<object[]>();
return something;
}
// Convert the c# object to that of what we expect to be returned,. string/int/bool/class
if (netObject != null)
result = (T)netObject; // convert the returned string to managed string object
}
return result;
}
catch (Exception)
{
// Handle your exceptions here
throw;
}
}
If you don't care about the entire function and just want the quick snippet of adding the params:
// Add parameters to the function?
if (paramset != null && paramset.Count > 0)
{
PyObject[] pyParams = new PyObject[paramset.Count]; // This is an array of python parameters passed into a function
// Loop through our incoming c# list of parameters and create PythonObject array .
for (int i = 0; i < paramset.Count; i++)
{
pyParams[i] = paramset[i].ToPython();
}
pythonReturn = pythonClass.InvokeMethod(functionName, pyParams); // Call the function on the class with parameters
}
else // We aren't using parameters here
pythonReturn = pythonClass.InvokeMethod(functionName); // Call the function on the class

Trigger C# method from JavaScript and send parameters

I'm trying to call a C# method from JavaScript and send parameters along with the call. I've done calls to web method but since I can't get to server side controls in static web method, I can't really use it in this case.
I can't do full postback because I need to get Google Map coordinates which in my case I'm accessing them this way, and I'm not able to access them differently:
var map = new google.maps.Map(document.getElementById("dvMap"), mapOptions);
var bounds = new google.maps.LatLngBounds();
bounds = map.getBounds();
var latLng = map.getCenter();
var latSW = bounds.getSouthWest().lat();
var lngSW = bounds.getSouthWest().lng();
var centerLat = latLng.lat();
var centerLng = latLng.lng();
So now since I want to pass some of these parameters to actual c# function it's ok even if I need to do full server side postback as long as I have the controls in my backend code.
Once on server side I need to populate asp.net repeater control with the dataset, that's the biggest issue why I need to trigger backend method.
public void GetData(string latSW, string lngSW, string latNE, string lngNE)
{
DataTable dt = this.GetData(latSW, lngSW, latNE, lngNE);
rptMarkers.DataSource = dt;
rptMarkers.DataBind();
RepDetails.DataSource = dt;
RepDetails.DataBind();
}
I'm unsure, from your question, whether you can or can't make a full post back so here's a fun javascript solution
function myawesomejavascriptfunction(latsw,lngsw,latne,lngne)
{
var myawesomeform=document.createElement('form');
myawesomeform.setAttribute('method','post");
myawesomeform.setAttribute('action','/myawesomewebendpoint');
var myawesomelatsw=document.createElement('input');
myawesomelatsw.setAttribute('type','hidden');
myawesomelatsw.setAttribute('name','latsw');
myawesomelatsw.setAttribute('value',latsw);
var myawesomelngsw=document.createElement('input');
myawesomelngsw.setAttribute('type','hidden');
myawesomelngsw.setAttribute('name','lngsw');
myawesomelngsw.setAttribute('value',lngsw);
var myawesomelatne=document.createElement('input');
myawesomelatne.setAttribute('type','hidden');
myawesomelatne.setAttribute('name','latne');
myawesomelatne.setAttribute('value',latne);
var myawesomelngne=document.createElement('input');
myawesomelngne.setAttribute('type','hidden');
myawesomelngne.setAttribute('name','lngne');
myawesomelngne.setAttribute('value',lngne);
document.getElementsByTagName('body')[0].appendChild(myawesomeform);
myawesomeform.submit();
}
The endpoint method at /myawesomewebendpoint will call the class with the GetData() method and pass on the parameters.
It will work, provided I've not got hold of the entirely wrong end of the stick.

Any faster solution for Powershell.Invoke?

I'm writing a CmdLet in C# and use the Powershell-Class and invoke different commands. Here my Code:
PowerShell poswershell;
public Construcor()
{
powershell = PowerShell.Create()
}
public Collection<PSObject> InvokeRestMethod(string uri)
{
return InvokePSCommand("Invoke-RestMethod", new[] { uri });
}
public Collection<PSObject> InvokePSCommand(string command, string[] args)
{
var execute = command;
execute = GetExecuteCommand(args, execute);
powershell.Commands.AddScript(execute);
return powershell.Invoke();
}
private static string GetExecuteCommand(string[] args, string execute)
{
if (args == null) return execute;
for (var i = 0; i < args.Count(); i++)
{
execute += " " + args[i];
}
return execute;
}
It works like I want, but really slowly. I want the same function, which gives me a Collection<PSObject> back. But when I call the InvokeRestMehtod several times, it takes a long time to get trough this.
Why I use this just for a simple WebRequest you ask?
The answer is, that I have to read from an uri (which returns json) some information. Fact is that the json structure is always different. Therefor the Invoke-RestMehtod gives me exactly what I need, a dynamic object(PSObject). I have to have this kind of object, because after that process I need to give this in the powershell user back, so he can pipeline the object and use it furhter.
My question is now, how could I get the same result, which I can pass into powershell, from an uri which return json?
EDIT
I found this dll=> Microsoft.PowerShell.Commands.Utility.dll, it includes in C# code the InvokeRestMethod-CmdLet what is called by the powershell. If I could read this code well, I could (would) use it in my code. Then I wouldn't create a PowerShell instance and invoke from my powershell-CmdLet an other CmdLet, which I do not like much and takes a way too long. Someone knows this dll and could help me to customize this code for my project?
I found dottrace and analyzed the process, here a screenshot I can't get any useful information out of that, perhaps someone of you? But I'm pretty sure Powershell.Invoke() takes most of the time while executing.
Why don't you reuse the same PowerShell object rather than create a new one each time? Each instantiation causes the PowerShell to have to initialize again. Just be sure to call powershell.Commands.Clear() between Invoke() calls.
I solved the problem now, here is the basic code which reads an uri (returns JSON) and returns an object:
private object InvokeRest(string uri)
{
return InvokeRest(uri, null);
}
private object InvokeRest(string uri, NetworkCredential networkCredential)
{
var webRequest = WebRequest.Create(uri);
if (networkCredential!=null)
webRequest.Credentials = networkCredential;
_webResponse = webRequest.GetResponse();
var streamReader = new StreamReader(_webResponse.GetResponseStream());
var str = streamReader.ReadToEnd();
ErrorRecord exRef;
var doc = JsonObject.ConvertFromJson(str, out exRef);
return doc;
}
Because I found out that every object you output in the powershell, converts in a PSObject and formats it.

Issue in Parsing Json image in C#

net C#. I am trying to parse Json from a webservice. I have done it with text but having a problem with parsing image. Here is the Url from where I m getting Json
http://collectionking.com/rest/view/items_in_collection.json?args=122
And this is My code to Parse it
using (var wc = new WebClient()) {
JavaScriptSerializer js = new JavaScriptSerializer();
var result = js.Deserialize<ck[]>(wc.DownloadString("http://collectionking.com/rest/view/items_in_collection.json args=122"));
foreach (var i in result) {
lblTitle.Text = i.node_title;
imgCk.ImageUrl = i.["main image"];
lblNid.Text = i.nid;
Any help would be great.
Thanks in advance.
PS: It returns the Title and Nid but not the Image.
My class is as follows:
public class ck
{
public string node_title;
public string main_image;
public string nid; }
Your problem is that you are setting ImageUrl to something like this <img typeof="foaf:Image" src="http://... and not an actual url. You will need to further parse main image and extract the url to show it correctly.
Edit
This was a though nut to crack because of the whitespace. The only solution I could find was to remove the whitespace before parsing the string. It's not a very nice solution but I couldn't find any other way using the built in classes. You might be able to solve it properly using JSON.Net or some other library though.
I also added a regular expression to extract the url for you, though there is no error checking what so ever here so you'll need to add that yourself.
using (var wc = new WebClient()) {
JavaScriptSerializer js = new JavaScriptSerializer();
var result = js.Deserialize<ck[]>(wc.DownloadString("http://collectionking.com/rest/view/items_in_collection.json?args=122").Replace("\"main image\":", "\"main_image\":")); // Replace the name "main image" with "main_image" to deserialize it properly, also fixed missing ? in url
foreach (var i in result) {
lblTitle.Text = i.node_title;
string realImageUrl = Regex.Match(i.main_image, #"src=""(.*?)""").Groups[1].Value; // Extract the value of the src-attribute to get the actual url, will throw an exception if there isn't a src-attribute
imgCk.ImageUrl = realImageUrl;
lblNid.Text = i.nid;
}
}
Try This
private static string ExtractImageFromTag(string tag)
{
int start = tag.IndexOf("src=\""),
end = tag.IndexOf("\"", start + 6);
return tag.Substring(start + 5, end - start - 5);
}
private static string ExtractTitleFromTag(string tag)
{
int start = tag.IndexOf(">"),
end = tag.IndexOf("<", start + 1);
return tag.Substring(start + 1, end - start - 1);
}
It may help

Convert C# to VB.Net - Using MVCContrib Blockrenderer to render a partial view to a string

I need to render a partialview to a string, and I am trying to convert a C# example to VB.Net, as I am stuck with that for this project.
This is causing me a headache from these two problems:
ObjectViewData - I can't figure out what that is
RenderPartial is a sub, but seems to be used as a function - I don' get it
I reference the MVCContrib.UI, so I don't need to convert that. But these two functions, I do need to convert:
(from brightmix.com)
/// Static Method to render string - put somewhere of your choosing
public static string RenderPartialToString(string userControl, object viewData, ControllerContext controllerContext)
{
HtmlHelper h = new HtmlHelper(new ViewContext(controllerContext, new WebFormView("omg"), null, null), new ViewPage());
var blockRenderer = new BlockRenderer(controllerContext.HttpContext);
string s = blockRenderer.Capture(
() => RenderPartialExtensions.RenderPartial(h, userControl, viewData)
);
return s;
}
/// Your Controller method...
public ActionResult MakeStringForMe()
{
var objectViewData = new objectViewData { SomeString = "Dude", SomeNumber = 1 };
string s = RenderPartialToString("~/Views/Controls/UserControl.ascx", objectViewData, this.ControllerContext);
View();
}
Here is my attempt at converting it to VB.Net
'Static Method to render string - put somewhere of your choosing'
Public Shared Function RenderPartialToString(ByVal userControl As String, ByVal viewData As Object, ByVal controllerContext As ControllerContext) As String
Dim h As New HtmlHelper(New ViewContext(controllerContext, New WebFormView("omg"), Nothing, Nothing), New ViewPage())
Dim blockRenderer As New MvcContrib.UI.BlockRenderer(controllerContext.HttpContext)
Dim s As String = blockRenderer.Capture(RenderPartialExtensions.RenderPartial(h, UserControl, viewData))
End Function
Public Function MakeStringForMe() As ActionResult
Dim objectViewData As objectViewData = New objectViewData With {.SomeString = "Dude", .SomeNumber = 1}
Dim s As String = RenderPartialToString("~/Views/Controls/UserControl.ascx", objectViewData, Me.ControllerContext)
View()
End Function
This line:
Dim s As String = blockRenderer.Capture(RenderPartialExtensions.RenderPartial(h, UserControl, viewData))
is NOT equivalent to your original line:
string s = blockRenderer.Capture(
() => RenderPartialExtensions.RenderPartial(h, userControl, viewData)
);
The C# example is using a lambda, while the VB example is just calling the method directly, which doesn't return a value. The compiler isn't lying to you.
Try this instead:
Dim s = blockRender.Capture(New Action(Of String)(Function() RenderPartialExtensions.RenderPartial(h, UserControl, viewData)))
I took a look at Capture and it's expecting an Action which is just a delegate, and it looks like the compiler can't infer the delegate's signature to wrap the anonymous function. So we'll give it a helping hand and wrap the lambda ourselves.
You could do it manually or try using http://www.developerfusion.com/tools/convert/csharp-to-vb/
EDIT: also your code has
View()
at the end of
Public Function MakeStringForMe()
this should be
Return View()
In response to point 2 the code isn't using the renderPartial sub it is using the RenderPartialToString function.
HTH
OneSHOT
RenderPartialToString needs to return a string, s
My favorite converter can be found at this link
The reason it's my favorite is that it can be used "offline"--that is, not at their web page. The converter is exposed as a web service, and there's sample code (in C#) to reference it.
I downloaded their sample code & adapted it to read & write from the file system. Made a conversion a whole lot simpler....
< edit> I know that link doesn't actually go to the converter--it goes to an "about" page, with links from there to the converter page & to the sample code download. Also, I should prob'ly mention that it's a three-cornered converter (VB, C# and Boo), bidirectional between any two languages < /edit>

Categories

Resources