Hooking all function calls in JavaScript? - c#

My intuitive response to this question would be ,"This is so stupid that I can't continue having this conversation." However:
Is there any way to hook all javascript function calls within my module? I'd like to find a convenient way of showing "loading blah...", "done..." messages when performing AJAX calls without having to explicitly place a call to a notification method in every AJAX method.
Also, is there any convenient way to set up a global exception handler in javascript?
It's perfectly possible, of course, to eliminate the need for either of these things by performing correct exception handling in every applicable method, but it would be nice to have a global "Whoops!" method to happily catch anything that managed to slip through due to programmer (ie, me) error.
Working in C#/ASP.NET if it matters or if there's a server-side gadget that could make this easier.

window.onerror will catch all of the errors. That's how Firebug and others work.
As for "every ajax method" you should just have 1 reusable ajax method, and have it be in charge of updating your status message.

If you only have ajax calls actually being made in one place, where the open and send commands are, then you can put in some logging, or notification there.
If you are using jquery, or some library that supports selectors, you can bind to the events of many objects.
The exception part was already answered.

You can look at all objects via
function show_props(obj, obj_name) { var result = "" for (var i in obj) result = obj_name "." i " = " obj[i] "\n" return result; }
That is from http://www.memestreams.net/users/acidus/blogid10323750/

I suggest that you use jQuery AOP plugin. I have used it for a large library.

Related

Can the C# compiler throw an error or warning if a certain method is called in a loop

Often times a developer on my team writes code in a loop that makes a call that is relatively slow (i.e. database access or web service call or other slow method). This is a super common mistake.
Yes, we practice code reviews, and we try to catch these and fix them before merging. However, failing early is better, right?
So is there a way to catch this mistake via the compiler?
Example:
Imagine this method
public ReturnObject SlowMethod(Something thing)
{
// method work
}
Below the method is called in a loop, which is a mistake.
public ReturnObject Call(IEnumerable<Something> things)
{
foreach(var thing in Things)
SlowMethod(thing); // Should throw compiler error or warning in a loop
}
Is there any way to decorate the above SlowMethod() with an attribute or compiler statement so that it would complain if used in a loop?
No, there is nothing in regular C# to prevent a method being used in a loop.
Your options:
discourage usage in a loop by providing easier to use alternatives. Providing second (or only) method that deals with collections will likely discourage one from writing calls in a loop enough so it is no longer a major concern.
try to write your own code analysis rule (stating tutorial - https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/tutorials/how-to-write-csharp-analyzer-code-fix)
add run-time protection to the method if it is called more often than you'd like.
Obviously it makes sense to invoke those slow methods in a loop - you're trying to put work into preventing that, but that's putting work into something fundamentally negative. Why not do something positive instead? Obviously, you've provided an API that's convenient to use in a loop. So, provide some alternatives that are easier to use correctly where formerly an incorrect use in a loop would take place, like:
an iterable-based API that would make the loop implicit, to remove some of the latency since you'd have a full view of what will be iterated, and can hide the latency appropriately,
an async API that won't block the thread, with example code showing how to use it in the typical situations you've encountered thus far; remember that an API that's too hard to use correctly won't get used!
a lowest-common-denominator API: split the methods into a requester and a result provider, so that there'd naturally be two loops: one to submit all the requests, another to collect and process the results (I dislike this approach, since it doesn't make the code any nicer)

File.ReadAllText with a lambda-based retry wrapper on Try Catch

Trying to find the most elegant solution for a situation when I get a "IOException: Sharing violation" on loading a JSON file because it is being saved at the same time by another application.
Using a "try Catch' with some form of recursion when loading, though inelegant, makes sense.
So after searching came across this C# solution which gets a lot of up votes
Cleanest way to write retry logic?
The actual function call where my load occurs is
private static T LoadData<T>(string filePath)
{
return JsonUtility.FromJson<T>(File.ReadAllText(filePath));
}
However not sure how to implement using the above linked solution (Retry.Do) which doesn't seem to allow passed arguments in the function call ie
Retry.Do(SomeFunctionThatCanFail, TimeSpan.FromSeconds(1));
Can anyone help?
You need to create a closure.
The simplest way is to use a lambda expression:
YourType data = Retry.Do(() => LoadData<YourType>("somefilepath"), TimeSpan.FromSeconds(1));

Calling an instance method using JSInterop - Notifying Blazor on input field change with JS

Placed here for the sake of it, originally I wrote this question on Blazors subreddit as it was an odd question.
Problem:
I need to call StateHasChanged to let Blazor know I've changed the input fields with JS (A library I have to implement, I'm stuck with this regardless so I need to find this solution.)
Description and solutions I've tried:
I've checked an issue created 2 years back, but it does not solve my issue as each time I follow their advice of dispatching the 'change' event, nothing happens. Although, that was tested by dispatching the event on the body element since it's difficult to pin point the exact element that needs to be updated. So my current solution is trying to call StateHasChanged in hopes I can get Blazor to see the changes to the field inputs.
Other info I found:
Checked here, but they don't show calling an instanced method, they just mention it's possible but not how.
Second, I checked here, but I'd prefer not to pass around an instance of a component, just to call StateHasChanged.
Maybe I don't absolutely need to call StateHasChanged and I'm just dispatching the 'change' event improperly but there's no good examples of dispatching that event to Blazor anyway so maybe that's an even better solution.
Additional solution I've tried.
Edit 1:
I have now managed to call StateHasChanged, mind you not the way I would like it to be called but I called it, and it made no difference, Blazor still doesn't recognize the changed inputs. Guess I'll be trying the 'change' event stuff.
code:
//button in Blazor component:
<button type="button" u/onclick='async (e) => await jsRuntime.InvokeAsync<Task>("ChangeValueFromJs", DotNetObjectReference.Create(this))'>Test</button>
//code in component:
[JSInvokable("invokeFromJS")]
public Task ChangeValue()
{
StateHasChanged();
return Task.CompletedTask;
}
//Javascript on client side page:
function ChangeValueFromJs(wrapper) {
return wrapper.invokeMethodAsync("invokeFromJS")
.then(_ => {
console.log('state has changed');
});
}
Edit 2 (Solution):
So I ended up going the JS route dispatching the 'change' event as a solution from SteveSandersonMS on an issue someone made on the Blazor repo very similar to mine. I did however learn two things that are very important for using this solution.
The event target for this dispatchEvent
(element.dispatchEvent('change', { 'bubbles' : true })), element in
this case, must be the input field, received from a querySelector
(let element = document.querySelector("#input-field-username"))
Bubbling should be true, although I haven't tested this, I think
someone mentioned it in one of my referenced pages that it is
important.
// Not the greatest but - submits an update for *all* input fields, not only the changed ones, maybe improve this later.
let elements = document.querySelectorAll(".address-form-input");
if (elements)
elements.forEach(p => p.dispatchEvent(new Event('change', { 'bubbles': true })))
Hopefully this helps anyone out there, cheers.

List-based publish subscribe pattern in c# (Wordpress hooks / filters)

I come from a PHP background and have used Wordpress quite a lot, I love how their plugin architecture works and the ability to hook events to event names. One of the best parts I like about it is being able to *add_filter()* to any database value just before it gets shown to the end user. My question is multi-part on how to replicate the whole plugin architecture in a C#.NET environment?
Part 1:
To create plug-ins I have researched the MEF framework would probably be the best (Managed Extensibility Framework -http://mef.codeplex.com/). This is designed specifically to take the grunt work out by giving you the ability to monitor directories for new plug-ins, tracking dependencies and other normal things. MEF ships with .NET 3.5+
Part 2
Hooking events? I can't seem to find much information about replicating a global channel based event system. From what I have upto yet I need a publish/subscribe pattern (which isn't that hard to make as you just create some concrete objects and give them events). The hard part is giving each event a 'channel' name and for all the events in the whole system to be part of a global collection (Mediator pattern).
To replicate: (http://codex.wordpress.org/Function_Reference/add_filter)
Example 1
// Add's my button to the end of the content
add_filter('the_content', 'my_plugin_button');
function my_plugin_button( $content ) {
// Add's my button to the end of the content
return $content . "<a href='#'>My button</a>";
}
OR
Example 2
// Add a new admin menu item by hooking in
add_action('admin_menu', 'my_plugin_menu');
function my_plugin_menu() {
add_options_page('My Plugin Options', 'My Plugin', 'manage_options', 'my-unique-identifier', 'my_plugin_options');
}
I hope your all with me upto yet? I have managed to replicate the functionality I need in Javascript and even jQuery has their .on() event function... same thing but channel or list based...
My 2 examples:
http://jsfiddle.net/AaronLayton/U3ucS/53/
http://jsfiddle.net/AaronLayton/eyNre/33/
Can anyone point me in the correct direction or is this the totaly wrong approach for c#?
I think NServiceBus can help you a lot with these issues. Udi Dahan which is the author of NServiceBus has also written a lot of articles about Domain Event pattern, which is a publish/subscribe mechanism.
Know it's been a long time since you posted this and you probably built something already. However I have been thinking about something like this myself. There are 2 options - really forget WordPress and try and build something much cleaner - it's a mess at the bottom of WordPress' code :D
Or this:
function the_content()
{
var result = get_the_content();
// do other stuff...if you want to.
execute_filters(ref result);
execute_actions(ref result);
return result;
}
function execute_filters(ref string result, string action_name)
{
var filters = get_pre_filters(action_name);
filters.ForEach(filter =>
{
/// somehow call the method name in filter. PHP is generally global. C# namespaced,
/// so you would need to think about that.
}
}
function execute_actions(ref string result, string action_name)
{
/// and so on....
}
When building something to mimic WordPress, you need to remember many of the issues of WordPress' plugin architecture (in my personal opinion)... It seems to want to run every plugin near enough on every page even if that page has nothing to do with that plugin. I onced installed a plugin that added 60 database queries to each page call, and it wasn't used.
Try and think smart about it when you are building it. Try and add a way to only have the plugins that are going to get used on the page/post of your new setup to be run e.g. in your database have a "Plugins" field on the post/page object with a list of plugins allowed to run on that page. That way you won't need to check all the plugins each time to see if it wants to run.
Anyways. Hope you got something working.

web service exception handling

I have a WebMethod that receives following types of parameters:
[WebMethod]
User(long userid,int number)
When Client sends parameter with different types from I want, I have to catch this error and write to database etc.
For example ArgumentExceptions...
How can I solve this?
Thanks.
Have you tried what happens when a client uses the wrong types?
I would expect the SOAP library to trap this and raise an exception.
Inside your own method you can only check the values of the incoming parameters. And that works just like inside a normal (non-web) method.
You can use the following approach:
Each web method will always return some sort of WebMethodResult.
For example
[WebMethod]
public WebMethodResult DoSomethng(guid p_userId)
{
IfMethodIsSuccessful()
{
WebMethodResultSuccess successResult = new WebMethod();
// Add required information into web method result object
return successResult;
}
else
{
WebMethodResultFailure failedResult = new WebMethodResultFailure();
return failedResult;
}
}
Idea here is that whenever web method is called it will return some sort of object.
In this case the WebMethodResult will be the parent class and WebMethodResultSuccess and WebMethodResult failure would inherit from the parent class.
Instead of IsMethodIsSuccessfull you can add your own logic, wrap everything into a try catch block and return success/failure results.
If you call the web methods from the java script or jquery, the exception won't be passed back to the client unless you use SOAP or some sort of alternative. By sending back custom objects, you can read them through javascrip/jquery and display appropriate message to the user.
Hope this makes sense.
In terms of logging, you should probably write a generic exception handling layer or look into open source alternatives.
You woulc catch specific exception and pass it to exception handling layer. Within that layer (dll) you'll log the exception either in the database or write into a flat file. DB is probably a better option since the data can be easily analysed.
Another alternative is to log into windows event log, but I personally don't like this because it's not that easy to produce statistics on the exceptions and I think it has a limit in size.

Categories

Resources