I have following code. dont have any clue why I am getting this error - Delegate Function doesnot take 1 arguments.
I am implementing a global Response handler which will be called by saveral requests.
Here is the HandleResponse function:
Response<T> HandleResponse<T>(Func<Response<T>> func)
{
try
{
Response <T> response = func();
if(response != null)
{
return response;
}
else
{
//display response.message
return default(Response<T>);
}
}
catch(ConnectionException e)
{
// func = e.Message.ToString();
Console.WriteLine(e.Message);
return default(Response<T>);
}
}
And here is my Calling Function:
Request.MyRequest request = new
Request.MyRequest()
{
param1= comment, param2 = users
};
SomeResponse response = HandleResponse<SomeResponse>(x => client.DoRequest(request, revision.Name, revision.RevisionNumber));
I am a C++ developer and very new to C#. I am not sure why I am getting this error. Please someone explain.
Thanks in advance.
By using x => client.DoRequest() you are calling the delegate with 1 Parameter (the x before =>).
But your delegate has no parameters so you have to call it like this
() => client.DoRequest()
Related
I'm writing an unhappy flow unit test.
In my code I setup a function to throw async and later I validate that the function was called once.
This scenario fails and succeeds irregularly, as sometimes it shows no calls were made and sometimes the function is called once (as planned).
Do you know why?
Let me know if any more code is needed.
Thanks!
The test:
[Fact]
public async Task ContainerScan_ControllerTest_ErrorFlow()
{
//Given
TestsRegistrar.ContainerClient.Reset();
TestsRegistrar.ContainerClient.Setup(x => x.MyAsyncFunc(It.IsAny<Guid>(), It.IsAny<List<ContainerScanRecord>>())).ThrowsAsync(new Exception("bad stuff happened"));
var controller = new ContainersRiskGeneratorController(TestsRegistrar.ContainersGenerator, new Mock<IExtendedLogger>().Object, new Mock<IExtendedLoggerEnricher>().Object);
var scanId = Guid.NewGuid();
//When
var result = await controller.SomeUpperFuncthatCallsMyAsyncFunc(scanId, new RiskGenerator.Dto.V3.ContainersScanRequest
{
ContainerRecords = new List<RiskGenerator.Dto.V3.SomeDto>
{
new RiskGenerator.Dto.V3.SomeDto{
params here
}
}
});
//Then
result.Should().BeEmpty();
TestsRegistrar.ContainerClient.Verify(x => x.MyAsyncFunc(It.IsAny<Guid>(), It.IsAny<List<ContainerScanRecord>>()), Times.Once, "Container Engine should be called once");
}
UDPATE #1: added the calling funcs
The code for SomeUpperFuncthatCallsMyAsyncFunc:
[HttpPost("someUrl/{scanId:Guid?}")]
[DisableRequestSizeLimit]
public async Task<IReadOnlyCollection<SomeDto>> SomeUpperFuncthatCallsMyAsyncFunc(Guid? _, [FromBody] ContainersScanRequest request)
{
try
{
Ensure.NotNull(nameof(request), request);
_extendedLoggerEnricher.Enrich(new { request.ScanId });
_logger.Info("GenerateContainerRiskAsync called", new { request.ScanId });
var response =
await _riskGenerator.TheCallingFuncToMyAsyncFunc(
request.ScanId,
request.ContainerRecords
.Where(x=> !string.IsNullOrEmpty(x.DockerFilePath))
.Select(ContainerScanRiskRecordDto.ToContainerScanRecord).ToList())
.ConfigureAwait(false);
return response.Select(VulnerableContainerScanRecordDto.ToContainerScanVulnerablerRecord).ToArray();
}
catch (Exception exception)
{
_logger.Error("Exception thrown during generate GenerateContainerRiskAsync", exception, new { request.ScanId });
StatusCode((int)HttpStatusCode.InternalServerError);
return new List<SomeDto>();
}
}
And the func that calls directly to MyAsyncFunc:
public async Task<List<(ContainerScanRecord record, ImageVulnerabilitiesDto vulnerabilities)>> TheCallingFuncToMyAsyncFunc(Guid id, IReadOnlyCollection<ContainerScanRecord> containerRecords)
{
try
{
return await
_containerEngineClient.MyAsyncFunc(id, containerRecords).ConfigureAwait(false);
}
catch (Exception exception)
{
_logger.Error($"[{id}] Could not generate GenerateContainerRiskDataAsync: {exception.Message}", exception);
throw;
}
}
UDPATE #2: figured it out!
Well... it turned out to be a nasty race condition with some other class that initialized the data.
That's why it happened randomly.
Sorry for the hustle and thank you all for your time.
As I found out recently, when function throws, its invocation can not be counted. So this is why you may experience such problems.
What you could do is to verify that logger logs an error (the same way you assert that your method was called).
I've used a method, which I want to stop executing the rest of the code when it's called.
The function is:
class Helper
{
public static void MessageTextQues(string text, Action action)
{
MessageQues messageQues = new MessageQues();
messageQues.lblText.Text = text;
messageQues.ShowDialog();
if (messageQues.DialogResult == DialogResult.Yes)
{
action();
}
if (messageQues.DialogResult == DialogResult.No)
{
return;
}
}
}
Call function is:
Helper.MessageTextQues(
$#"This material '{dgMaterials.CurrentRow.Cells[2].Value}' will delete. Do you want? ",
() => material.MaterialDelete(Convert.ToInt32(dgMaterials.CurrentRow.Cells[1].Value)));
btnRefresh_Click(sender, e); //This code I don't want to read when No is selected
Maybe have MessageTextQues return a bool, so you can return true; (at the end) or return false; (when escaping early due to an invalid state), to indicate whether to proceed, and use:
if (Helper.MessageTextQues(...))
{
btnRefresh_Click(sender, e);
}
You can put the code into the action you pass to your MessageTextQues method:
Helper.MessageTextQues(
$#"This material '{dgMaterials.CurrentRow.Cells[2].Value}' will delete. Do you want? ",
() =>
{
material.MaterialDelete(Convert.ToInt32(dgMaterials.CurrentRow.Cells[1].Value));
btnRefresh_Click(sender, e);
});
Can someone please put another set of eyes oh this? I am trying to validate that a blob image exists prior to displaying. This could take 1-4 seconds.
my JS looks like this:
var url = '/api/blob/ValidateBlobExists?id=' + blobImage;
$.getJSON(url,
function(json) {
console.log("success");
})
.done(function () {
console.log("second success");
exists = data;
if (exists) {
console.log("exists'");
$('#imgPhotograph').hide().attr('src', blobImage).fadeIn();
} else {
$('#imgPhotograph').attr('src', '../Images/NoPhotoFound.jpg');
}
});
the api looks like this.. please don't judge.. its vb because it has to be.
Public Function ValidateBlobExists(id As String) As JsonResult(Of Boolean)
dim result = CDNHelper.BlobExists(id) 'this could take ~5 seconds
Return Json(Of Boolean)(result)
End Function
the underlying method looks like this:
public static bool BlobExists(string filename)
{
try
{
var sw = new Stopwatch();
sw.Start();
do
{
if (client.AssertBlobExists(filename).Result) // <-- this is a wrapper to query the azure blob
return true;
System.Threading.Thread.Sleep(500); //no reason to hammer the service
} while (sw.ElapsedMilliseconds < 8000);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
return false;
}
the thing is in my console output I can't even get to the "success". It seem the getJson() is just not willing to wait for the 8 seconds to elapse before continuing. Any thoughts are appreciated .
The issue was that my API response signature was not decorated as Async. Even though I was calling .result it was getting messed up. The solution for me was to modify my code as below
Public Async Function ValidateBlobExists(id As String) As Task(Of JsonResult(Of Boolean))
result = await CDNHelper.BlobExists(id, "ioc")
return result
End function
and
public static async Task<bool> BlobExists()
{
return client postasync wrapper
}
I am working out how best to consume my C# dlls using Edgejs for Node.
One proxy function in Node looks like this (a class method in Typescript):
readSettings(args: ReadSettingsParams) : Promise<response> {
let $engine = this;
var proxy = edge.func({
assemblyFile: "C:\\Development\\IAStash\\GLReport\\GLReport\\bin\\x64\\Debug\\GLReportEngine.dll",
typeName: "GLReportEngine.edgeGLReport",
methodName: "readSettings"
});
return new Promise<response>(function (resolve, reject) {
args.instance = $engine.instance;
proxy(args, function(error, result) {
if (error) {
reject(error);
} else {
resolve(result);
}
});
});
}
When my complex task in c# is synchronous, everything works as expected, but when I move the core of the c# function into a task:
return await Task.Run<object>( () => { do some stuff });
When I use the above pattern, the resolve(result) line is hit, the result is correct in the watch window, but any .then or Q.all structures that are composed do not respond to resolve(result) having been executed.
I have found that if I console.log("x"); before the proxy callback returns, then my composed .then and Q.all structures fire as expected. i.e. this version works:
readSettings(args: ReadSettingsParams) : Promise<response> {
let $engine = this;
var proxy = edge.func({
assemblyFile: "C:\\Development\\IAStash\\GLReport\\GLReport\\bin\\x64\\Debug\\GLReportEngine.dll",
typeName: "GLReportEngine.edgeGLReport",
methodName: "readSettings"
});
return new Promise<response>(function (resolve, reject) {
args.instance = $engine.instance;
proxy(args, function(error, result) {
console.log("GLReportProxy.readSettings proxy returns, Err = " + (!!error));
if (error) {
reject(error);
} else {
resolve(result);
}
});
});
}
My c# routine in this case reads an xml file, deserializes it and returns it:
public Task<object> readSettings(object args)
{
if (args != null && typeof(System.Dynamic.ExpandoObject).IsAssignableFrom(args.GetType()))
{
var argdict = (IDictionary<string, object>)args;
if (argdict.ContainsKey("report"))
{
reportsettingsfile = argdict["report"].ToString();
}
return Task.Run<object>(
() => {
if (File.Exists(reportsettingsfile))
{
var xser = new XmlSerializer(typeof(ReportSettings.report));
string settingstext = File.ReadAllText(reportsettingsfile);
using (var tre = new StringReader(settingstext))
{
reportSettings = (ReportSettings.report)xser.Deserialize(tre);
}
return new { result = true, model = reportSettings };
}
else
{
return new { result = false, error = "File not found" };
}
});
} else
{
return Task.FromResult<object>(new { result = false, error = "Expected (input) object but can't read it." });
}
}
This is fairly simple. I figure that I've got problems in my use of async/await, that causes problems in Node. To be fair though, I had expected promises to be robust. There could be issues with my use of Typescript, Node, Edge, Promises, Q.
If anybody knows what's happening, and why logging to the console fixes the problem. I'd appreciate any help!
Mark
I found that this is an issue when there is a http.listener and a c# edge proxy callback in the same process. There could be other combinations, but some interplay between libraries is the root cause.
Since this issue is unresolved according to edgejs, the console.log method is a good workaround, particularly if you don't mind writing some helpful message to the log window.
console.log is a good workaround, but I wanted something silent. I notice that console internally has _stdout. If you execute console._stdout.write(''); you get a silent unlock. in Typescript you have to do (console as any)._stdout.write('');.
I do this on entry to the edge proxy callback. e.g.
readSettings(args: ReadSettingsParams) : Promise<response> {
let $engine = this;
var proxy = edge.func({
assemblyFile: "C:\\Development\\IAStash\\GLReport\\GLReport\\bin\\x64\\Debug\\GLReportEngine.dll",
typeName: "GLReportEngine.edgeGLReport",
methodName: "readSettings"
});
return new Promise<response>(function (resolve, reject) {
args.instance = $engine.instance;
proxy(args, function(error, result) {
(console as any)._stdout.write('');
//console.log("GLReportProxy.readSettings proxy returns, Err = " + (!!error));
if (error) {
reject(error);
} else {
resolve(result);
}
});
});
}
Clearly you could log something as indicated in the comment.
I want to write an extension method that will run a method of some object, and return the exception that occurred during execution (if any).
In other words, make this dynamic for myObject.Foo() to be anyObject.AnyMethod(...).
Exception incurredException = null;
try
{
myObject.Foo();
}
catch(Exception e)
{
incurredException = e;
}
return incurredException;
To this:
Exception e = IncurredException( () => myObject.Foo() );
I have no idea if a Func, Expression, Delegate, etc. is appropriate here. Thoughts? Thanks!
Assuming you don't care about return types, you need something like this:
public static Exception IncurredException(Action action)
{
try
{
action();
}
catch (Exception e)
{
return e;
}
return null;
}
You can then invoke it as you wanted with:
Exception e = IncurredException( () => myObject.Foo() );
Or a bit tidier, using var and method group syntax:
var e = IncurredException(myObject.Foo);