Is there a more efficient syntax for mutliple try/catch? - c#

I have a callback web method that Facebook is calling. Unfortunately, the purpose of the call using this single url is determined solely by the structure of the object (json) that is passed in the Post body. Right now, I am thinking of:
try { Class1 obj1 = JsonConvert.DeserializeObject<Class1>(rawData);
//code to run if data is of Class1 ...
}
catch
{ try { Class2 obj2 = JsonConvert.DeserializeObject<Class2>(rawData);
//code to run if data is of Class2 ...
}
catch
{ Class3 obj3 = JsonConvert.DeserializeObject<Class3>(rawData);
//code to run if data is of Class3...
}
}
Is there a cleaner better way than the above?

Ideally, you shouldn't use exceptions to drive decisions on code paths that do not deal with exceptional situations. If this is something that you cannot avoid, you could set up a loop that tries different classes, like this:
var deserializers = new Func<string,object>[] {
(rawData) => JsonConvert.DeserializeObject<Class1>(rawData)
, (rawData) => JsonConvert.DeserializeObject<Class2>(rawData)
, (rawData) => JsonConvert.DeserializeObject<Class3>(rawData)
};
object result = null;
foreach (var d in deserializers) {
try {
result = d(rawData);
break;
} catch {
// Conversion was unsuccessful
}
}
If deserializing went OK, break statement is reached, and your loop exits. Otherwise, the loop continues to the next iteration, until the loop succeeds, or we run out of deserializers.
Note: An explicit cast may be required in order to put functors into an array:
(rawData) => (object)JsonConvert.DeserializeObject<Class1>(rawData)

Related

Making a transaction-like behaviour when interacting with multiple systems

Disclaimer
In the following post:
action= Action/Func
I have a long method that does multiple actions(s).Each action is wrapped in a try-catch.If the specific action fails , in the catch i must perform a clear action for all previous ones and the current one.
I do not know a way to stop duplicating code in the catch and aggregate them using a design pattern or something.
What i have currently
public void LongMethod()
{
try
{
try
{
action1();
}catch(Exception ex)
{
ClearAction1();
}
try{
action2();
}catch(Exception ex){
Clearaction1();
Clearaction2();
}
try
{
action3();
}
catch(Exception ex)
{
Clearaction1();
Clearaction2();
Clearaction3();
}
catch(Exception ex)
{
//how should i aggregate the action clearance here
}
}
In the above method i do not want to write in all catch blocks all the clear actions up until that point.
I would like for each successful action to set something like a checkpoint , and then when that fails , check the state and perform all required clearing up until that point.
What i would like
public void LongMethod()
{
try
{
int checkpoint=0;
action1();
checkpoint=1;
action2();
checkpoint=2;
action3();
checkpoint=3;
action4(); //fails here
}
catch(Exception ex)
{
switch(checkpoint)
{
3//does Clearaction1()+Clearaction2()+Clearaction3()+Clearaction4();
}
}
}
I was thinking if there is something like a design pattern to wrap each of these actions which might have different return types and pipeline them.Whichever actionN fails it triggers Clearaction1()...ClearactionN() where N is the Action that did fail.
P.S It might be something like a monad.
m a ->(a->m b) -> m b -> (m b -> (b -> m c) -> m c) -> (m c -> ( c -> m d) -> m d)
where a ,b,c,d are types the difference being that i need to aggregate all failure treatment.
Update
After answers on this forum i felt i needed to do some additions:
This is an endpoint inside a ASP NET Controller.I retrieve data from multiple systems and with the fetched data i am setting other systems.
What i want to this to look like is like a distributed system transaction:
Fetch Input Systems [A,B]
To Output Systems [X,Y]
Example of sequence
fetch data from A
set data on X (using A data) (and get response Z)
fetch data from B
set data on Y (using data fetched from B and Z)
Secenario
Now lets say the the fetch data from B fails i want to:
- clear data from X only
I do not want to attempt to clear data on Y since it would produce irrevocable damage.
I care only about the I/O actions that set data.
If your code is not very-very performance/allocation critical you can just create a list of "reverse actions" and boolean variable to track success:
public void LongMethod()
{
var reverseActions = new List<Action>();
var success = false;
try
{
int checkpoint=0;
Action1();
reverseActions.Add(ClearAction1);
Action2();
reverseActions.Add(ClearAction2);
...
success = true;
}
finally // or can be catch if you can/want to handle/swallow exception
{
if(!success)
{
foreach(var a in reverseActions)
{
a();
}
}
}
}
It seems you could simply build a list of pairs of actions and the corresponding compensating action. Then iterate from 1 to N, applying each action. If an exception is caught in step I, iterate backwards from I to 1 through the list of compensating actions.
Also, it is possible to use monads for compensation, e.g. the cats-saga library for Scala cats
If you are able to have one state object, that takes all "side-effects", you can do something like this:
public State LongMethod( State originalState ) // assuming, `State` is your state object type
{
// vv Copy-CTOR == "Begin Transaction"
State localState = new State(originalState);
try{
// mutate _the local copy_
action1(localState);
var intermediateResult = func2(localState);
action3(localState, intermediateResult);
// ...
return localState; // return mutated state == "Commit"
}
catch(Exception ex)
{
// return unchanged state == "Rollback"
return originalState;
}
}
Why did I bother to add this after a different answer has already been accepted?
I wanted to present this alternative, regarding Martin's comment:
Perhaps not relevant to your question, but have you considered what will happen if your process terminates in the middle of this "transaction"?
If the process terminates amidst above code, you have a consistent state: the unchanged one.
Downside is: It really only works if you can isolate a state and do not depend on events triggered in the process.
To make it more clear: If in the process, let's say action5 does a HTTP PUT to API XYZ, then this solution is not enough because you would have to actively reverse that PUT.

Best way to debug yield return that is consumed during serialization?

I'm working on an application that embeds JSON within the page. Some simplified example:
public ViewResult Page(IEnumerable<LolCat> lolCats)
{
var json = new
{
localCats = ToJson(lolCats),
};
return View( json ); // this gets serialized somewhere in the ASP pipeline
}
IEnumerable<object> ToJson(IEnumerable<LolCat> lolCats)
{
foreach ( var lolCat in lolCats )
yield return new { name = lolCat.name };
}
The JSON gets automatically serialized somewhere down the line in the ASP.NET pipeline.
In this example assume that sometimes a NULL slips into lolCats, throwing an exception. Problem is that the ToJson function might be called at a lot of different places throughout the application.
How do I find out which call to ToJson was the one responsible for the exception? The call stack ends in the Serializer that is actually consuming this IEnumerable, and therefore you don't see the 'original stacktrace'.
One simple fix would be to call ToList() within Page. But I'm looking for a way that doesn't break the laziness of the method.
Due to the deferred nature, you will never get which call to ToJson() actually produced the exception. The collection was never inspected in the first place until it was first enumerated (when it was serialized).
You need to inject into your enumerator some info about what called it.
e.g.,
IEnumerable<object> ToJson(IEnumerable<LolCat> lolCats, string id)
{
try
{
foreach (var lolCat in lolCats)
yield return new { name = lolCat.name };
}
catch (Exception ex)
{
throw new Exception(id, ex); // use a more appropriate exception
}
}
Then it's just a matter of generating an id that could help identify the caller.

is it good to use try-finally just to make sure that something is performed when method finished?

My method returns in many points. I construct newData during execution also in many points. Regardless of where I return I need to save and store constructed result. Not to miss "return" I just surrounded the code with try-finally block so now I'm sure that newData will be stored.
List<X> newData = new List<X>();
try
{
....
update newData
.....
return;
.....
....
update newData
....
update newData
return;
.....
return;
} finally
{
// copy newData to data
}
But I don't catch any exceptions and this code is not intended to work with exceptions. Is it acceptable in general or you can suggest another better approach?
I would suggest refactoring the code within the try block into a new method:
data = CreateList();
...
private List<X> CreateList()
{
List<X> list = new List<X>();
// It's fine to return list from any point here...
}
The usage of finally is intended as a backup if something fails(think of it as a fail-safe mechanism), including atomicity etc.
Generally the whole construction of your method is wrong and you can refactor it, as getting all those returns usually means you can take up another approach to things(example using a switch as someone in the comments suggested).

Cannot access a disposed object

Hi could you help me with this error?
Cannot access a disposed object.
Object name: 'DataContext accessed after Dispose.'.
in my GUI
private void InitializePage()
{
cbCategory.DataSource = stock.StockCategory.Get();
}
in Datamodel
public IEnumerable<StockCategory> Get()
{
using (leDataContext db = new leDataContext())
{
try
{
var r = from s in db.StockCategories
select s;
return r;
}
catch (Exception ex)
{
Logger.Error(typeof(StockCategory), ex.ToString());
throw;
}
}
}
You're disposing the DataContext but returning something that still depends on it.
Options:
Don't dispose the DataContext. I know this sounds weird, but guidance from the LINQ to SQL team (well, Matt Warren) has indicated that in most cases (i.e. if you're not doing anything out of the ordinary) disposal is not required
Call ToList() inside the Get() method's using block.
Note that using a query expression with just a degenerate query is reasonably pointless. (If this is within your own code, even the implicit Select(s => s) won't actually be useful.)
I would suggest changing your method to:
public IList<StockCategory> GetAllStockCategories()
{
using (leDataContext db = new leDataContext())
{
return db.StockCategories.ToList();
}
}
Because of lazy-loading there, the query isn't really executed on the linq statement line. It is executed when you loop over it, or in this case - when you run ToList on it.
When it is executed it must be inside the data context... which is not the case here. You can either return a List from the Get method or insert the setting of the cbCategory.DataSource value into the using (leDataContext...) scope.

Writing code to fire the last method to throw an exception in a multi-threaded web app

I was writing some try-catch blocks for various methods today, and thought to myself it would be good to have utility method which would automatically call the method again for a number of times specified in a parameter, at a certain time.
However, I thought to myself, the method/property etc which will cause an exception will be at the top of the stacktrace (do property calls get put on the stacktrace?) in a single threaded application (so an application with no code relating to threading). So I can simply get the method name at the top and dynamically call it again.
So I would have code like:
string s = StackTrace.GetFrame(0).GetMethodName; (I can't remember the exact syntax).
With this method, I can execute it using an activator or one of several other ways.
But in a multi-threaded application, I could have several methods firing at once and I wouldn't know which one finishes first/last. So I can't expect a method for which I write a try-catch block to be at the top of the stack.
How would I go about achieving this?
Please don't do this. It's a really, really, really, really, really bad idea.
Maybe not as bad as deleting files randomly, if the hard drive runs out of room - but just about as bad.
While I question the need for an auto retrying mechanism (does randomly retrying really help you out in so many situations that you need a utility method?) - using StackTrace and Reflection is, at best, a terribly complicated solution.
Not that I suggest that anyone actually use this code, but I'd probably go with a delegate based approach to this particular problem:
public static class Extensions {
public static void Try(this Action a, int maxTries) {
new (Func<bool>(() => { a(); return true; })).Try(maxTries);
}
public static TResult Try<TResult>(this Func<TResult> f, int maxTries) {
Exception lastException = null;
for (int i = 0; i < maxTries; i++) {
try {
return f();
} catch (Exception ex) {
lastException = ex;
}
}
throw lastException;
}
}
Usage is a bit unorthodox, but fairly clear I think:
// Set a property
new Action(() => myObject.Property = 5).Try(5);
// With a return value
var count = new Func<int>(() => myList.Count).Try(3);
You can't inline a lambda to a method, but you could have a somewhat fluent interface:
Utilities.Try(
() => MyObject.Property = 5
).Repeat(5);
And multi line methods:
Utilities.Try(() => {
MyObject.Property1 = 5;
MyObject.Property2 = 6;
MyObject.Property3 = 7;
}).Repeat(5);
Mark's code is probably better, but here's mine...
If you really want to do something like this, I'd use code something like this. Yes, you still have to manually call it, but your idea of indiscriminately retrying ALL excepting methods is a really, really bad idea.
public class TryAgain
{
public delegate void CodeToTryAgain ();
public static void Repeat<E>(int count, CodeToTryAgain code) where E : Exception
{
while (count-- > 0)
{
try
{
code();
return;
}
catch (E ex)
{
Console.WriteLine("Caught an {0} : {1}", typeof(E).Name, ex.Message);
// ignoring it!
}
}
}
}
And then you'd call your failing method, ThrowTwice, or whatever you want to do, like this:
TryAgain.Repeat<MyException>(5, delegate()
{
ThrowTwice();
});
In this example, the Repeat method will ignore all exceptions of type MyException, trying to call ThrowTwice up to 5 times...
You can add your own sleeping and time-outs, and whatever.

Categories

Resources