How to return response from webservice - c#

I have made a web service and clients will call its methods. Suppose one method takes four parameters and I want to check that if any one of these is empty I want to send a response back to the client and I want to send it like an alert so client knows what argument is empty. I can not force client to give all parameters accurate. Is this possible?
[WebMethod]
Public void Method1(string str1,string str2,string str3,string str4)
{
if((str1=="") || (str2==""))
{
//send response back to client in form of an alert
}
}

As far as I know, you can send some agreed-upon object back to the sender, which the sender should be prepared to receive. It could be as simple as a string that contains "OK" or "ERROR", or it could be complex and have an error code, description, severity level, etc. What the sender does with it when they consume it is completely up to them though.
You could, for instance, make one of the fields in your response a severity level (maybe using something like Microsoft's Severity enum), which the sender could then use to determine whether they display an alert to their users or simply log the error somewhere on their system.

Don't reinvent the wheel with custom objects. Look at this MSDN article.
The easiest thing is just to throw an exception (sounds like an ArgumentException is appropriate in your case) and the client will receive a SoapException.
Or throw a SoapException yourself if you want more control, such as the ability to set a fault code.

You said you can't control the person calling the web method. As the method is of type void, the user will only know if something drastic happens. How about throwing an exception, and the error will propagate, to what detail it depends on the settings of the web server hosting the web service and the web server hosting the client (if the client is a web page).
throw new Exception("str1 or str2 in Method1 is empty");
In the "best" case, the user will see the error message "str1 or str2 in Method1 is empty. In the "worst" case, the user will get the standard IIS/ASP.NET error page. Like you said you have no control over the caller, it depends on how the caller codes the client and how he deploys the application. But whatever the case, it gets his attention!
I put best and worst in quotes because best and worst mean different things to different people. For people who want maximum security, best is when the error page says nothing about the error. For people who want user friendliness and fast troubleshooting, best is when the error message has a lot of details and what to do next.

Related

MassTransit Activity Fault with parameters

I am currently using Masstransit in with the Courier pattern.
I´ve set up an Activity which may fail, and I want to be able to subscribe to this failure and act accordingly.
My problem is, even though I can subscribe to the failure, and even see the exception that caused the failure, I am unable to pass any arguments to it.
For testing purposes, supose I have the following activity:
public class MyActivity : ExecuteActivity<MyMessage>
{
public Task<ExecutionResult> Execute(ExecuteContext<MyMessage> context)
{
try
{
// .... some code
throw new FaultException<RegistrationRefusedData>(
new RegistrationRefusedData(RegistrationRefusedReason.ItemUnavailable));
// .... some code
}
catch (Exception ex)
{
return Task.FromResult(context.Faulted(ex));
}
}
}
The problem is in the reason (RegistrationRefusedReason) I am passing as a argument of the exception. If I subscribe a RoutingSlipActivityFaulted consumer, I can almost get all the information I need:
public class ActivityFaultedConsumer : IMessageConsumer<RoutingSlipActivityFaulted>
{
public void Consume(RoutingSlipActivityFaulted message)
{
string exceptionMessage = message.ExceptionInfo.Message; // OK
string messageType = message.ExceptionInfo.ExceptionType; // OK
RegistrationRefusedReason reason = ??????;
}
}
I feel like I am missing something important here, (maybe misusing the pattern?).
Is there any other way to get parameters from a faulted activity ?
So, the case you're describing isn't a Fault. It's a failure to meet a business condition. In this case, you wouldn't want to retry the transaction, you'd want to terminate it. To notify the initiator of the routing slip, you'd Publish a business event signifying that the transaction was not completed due to the business condition.
For instance, in your case, you may do something like:
context.Publish<RegistrationRefused>(new {
CustomerId = xxx,
ItemId = xxxx,
Reason = "Item was unavailable"
});
context.Terminate();
This would terminate the routing slip (the subsequent activities would not be executed), and produce a RoutingSlipTerminated event.
That's the proper way to end a routing slip due to a business condition or rule. Exceptions are for exceptional behavior only, since you'll likely want to retry them to handle the failure.
Kinda raising this from the dead, but I really haven't found a neat solution to this.
Here is my scenario:
I want to implement a request/response, but I want to wait for the execution of a routing slip.
As Fabio, I want to compensate for any previous activities and I want to pass data back to the request client in case of a fault.
Conveniently, Chris provided a RoutingSlipRequestProxy/RoutingSlipResponseProxy which does just that. I've found 2 approaches, but both of them seem very hacky to me.
Approach 1:
The request client waits for ISimpleResponse or ISimpleFailResponse.
RoutingSlipRequestProxy sets the ResponseAddress in the variables.
The activity sends ISimpleFailResponse to the ResponseAddress.
The client waits for either response
The RoutingSlipResponseProxy sends back Fault<ISimpleResponse> to the ResponseAddress.
From what I see the hackiness comes from step 4/5 and their order. I am pretty sure it works, but it could easily stop working in case messages are consumed out-of-order.
Sample code: https://github.com/steliyan/Sample-RequestResponse/commit/3fcb196804d9db48617a49c7a8f8c276b47b03ef
Approach 2:
The request client waits for ISimpleResponse or ISimpleFailResponse.
The activity calls ReviseItirery with the variables and adds a faulty activity.*
The faulty activity faults
The RoutingSlipResponseProxy2 get the ValidationErrors and sends back ISimpleFailResponse to the ResponseAddress.
* The activity needs to be Activity and not ExecuteActivity because there is no overload of ReviseItinerary with variables but with no activity log.
This approach seems hacky because an additional fault activity is added to the itinerary, just to be able to add a variable to the routing slip.
Sample code: https://github.com/steliyan/Sample-RequestResponse/commit/e9644fa683255f2bda8ae33d8add742f6ffe3817
Conclusion:
Looking at MassTransit code, it doesn't seem like a problem to add a FaultedWithVariables overload. However, I think Chris' point is that there should be a better way to design the workflow, but I am not sure about that.

Handle an unreliable/unresponsive SOAP web service or REST API from a C# applicaiton

I don't like error handling via try catch blocks but in this case I did not see any other clear path. In my code I'm calling a web service but it might soon be a rest API in the near future. This web service is external and unfortunately not 100% reliable. What I need to do is create code that can handle an unresponsive web service. Today it looks like this:
SOAP Proxy is set to have a timeout of 120 seconds
var myProxy = new WebReference.ProxyClass();
myProxy.Timeout = 120000;
try
{
CreditInformation creditInformation = myProxy.Retrieve(prospect.CorporateIdentity);
agreement.Company.Name = creditInformation.CompanyName;
agreement.FinancialInformation.NetRevenue = creditInformation.Revenue / 1000;
}
catch (WebException e) when (e.Status == WebExceptionStatus.Timeout)
{
logger.Error("Web service timed out");
}
//Continiue running code even if the web service time out
Is this a bad standard and could it be better performed? As I said before I don't like handling errors via try catch but it seemed viable here. I thought about creating some code to check if the web service was responding but i decided not to go this way. This is because the web service is quite slow, a request takes 30-60 seconds by default and that would leave the user waiting even longer for me to check if it is up. Another solution might be to ping the host but it does not guarantee that the service is actually up. Sample code:
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response != null && response.StatusCode == HttpStatusCode.OK)
{
//Do stuff here
}
There are two opposite camps about how to handle exceptional situations. One camp prefers exceptions, another camp prefers to return error codes (or similar) from a function that might fail in one form or another. What is "better" is arguable and situation-dependent (see for example: http://www.joelonsoftware.com/items/2003/10/13.html for the arguments of "error code" camp). I'm telling this because as I understand you would prefer that myProxy.Retrieve return some error code on timeout, not throwing an exception. It might be reasonable, but that's not how it works and you cannot change that. Whole .NET framework uses exceptions almost everywhere (sometimes in situations which might be considered "part of normal flow", though definition of normal flow is again not trivial).
Long story short - a lot of code you use in .NET will throw exceptions on errors, even in sutations which you consider normal, and you have to live with that and act accordingly - catch and handle them - that's perfectly normal. Usually there are 2 points against exceptions:
They cost some time and resources to construct, as you mention in comment. That's reasonable concern in some code which executes thousands of operations per second, and those operations throw thousands of exceptions. In your case however, request takes 30-60 seconds, and as such cost of exception is absolutely zero compared to that.
They change control flow, sometimes moving it very far from actual exception source (like goto statement). To handle this (if you are in the "error code" camp, but have to work with exceptions anyway), you should put try-catch block as close as possible to the function which produces it, and handle exception immedatly, because you know exactly where and why it happened. This if what you already do in your example.
So, surrounding soap service call with try-catch block and handling timeout exception is the best way to go here, and there is absolutely no need to try to avoid this exception being thrown. You might want to not throw exceptions in "normal" conditions yourself, in your own code, but if that happens in third party code - you have to handle and not avoid them.

"Callback Error: Invalid response from server" from C# ASP.Net application

I have an ASP.Net application with a button containing the following Javascript to be invoked when it is clicked:-
function calculate() {
sectionIndex = getSelectedRadioIndex("section");
compositionIndex = getSelectedRadioIndex("composition");
CallBackOU.callback( "calculate" , sectionIndex, compositionIndex );
}
I can verify that control reaches the last line of this function by setting a breakpoint on it. But instead of invoking the method in the code-behind file...
protected void CallBackOU_Callback (object sender, ComponentArt.Web.UI.CallBackEventArgs e)
{
//blah blah
}
I get a dialogue reporting
Callback Error: Invalid response from server.
This dialogue appears three times, after which the page sits there doing nothing (forever, so far as I can make out).
I can't find any information about this. Can anyone give me any clues or pointers about how to go about diagnosing the problem?
Without seeing the signature of the calculate callback method this is only a shot in the dark but some issues i have encounter when invoking web methods from javascript are make sure the method is properly decorated [WebMethod], make sure the method is static, make sure the parameters are of the correct type and named properly (they are infact case sensitive when deserializing JSON iirc). A little more information regarding how the call is made (JSON/XML) and the signature might help. Also, you can try using fiddler to see if you get any more information regarding the error.

Exceptions in validation

I currently have some code that delibratly throws an exception if the user sends me data that fails validation (see below). I like it because im sure any errors in the application are caught and handled. A am however worried the code being slow as throwing exceptions takes a lot of memory. Im also worried it might be "bad code". Whats your advice? Thanks
public class BTAmendAppointmentRequest
{
public DataLayer.WebserviceMessage AddBTAmendAppointmentRequest(DataLayer.BTAmendAppointmentRequest req)
{
DataLayer.WebserviceMessage rsp = new DataLayer.WebserviceMessage();
try
{
if (!String.IsNullOrEmpty(req.AppointmentReference))
req.AppointmentReference = req.AppointmentReference.Trim();
if (req.OrderRequestID < 1 || string.IsNullOrEmpty(req.AppointmentReference))
{
throw new Exception("Amend appointment failed, you must supply a valid appointment reference and order reference");
}
...Do other stuff
}
catch (Exception ex)
{
rsp = new Service.WebserviceErrorMessage(ex);
}
return rsp;
}
}
If you are expecting these errors, you should return error messages to the user, not throw exceptions.
Reserve exceptions to exceptional situations.
Apart from being expensive, the meaning of an exception, the semantics are that of something exceptional having happened. Validation failing is not exceptional, it is expected.
Having said that, seeing as you are on a web service, an exception is a reasonable thing to do, assuming you also validate before the service call. It is reasonable since a web service can be called by anything - validation may not have happened, and such errors should be exceptional. Additionally, at least with .NET web services, web exceptions are probably the best way to communicate such things back to the client.
Exceptions should be considered as last resort error trap. They should be "exceptional". Data input errors are not exceptions - they are very common, expected events. You shoudl handle validation issues with validation controls or processes, that handle them - display an error message and do not let the processing continue.
Your other problem is that you cannot easily do full form validation if the first error you encounter throws an exception. If I was filling out a form where each error was separately highlighted, I would give up very quickly. You need to be able to validate and display ALL errors on a page, and not permit progress without validation succeeding.
I tend to agree with Oded in that exceptions should only be used for stuff you aren't expecting. The other way to look at it is with using an errors collection, you are able to validate a larger batch instead of throwing an exception on the first problem. This can be more usable for the person consuming your service.
In the case of web services, I would package the entire response in a custom response object, which features a return code. This allows you to have a return code of error, and then encapsulate an errors collection in the response object.

WCF web service call - which exception(s) to catch?

I have a program that calls an external web service, and I want to present the user with a friendly dialog if e.g. the server is down, someone cut the cable etc. Assuming the following code
try {
client.MyWebService()
}
catch(? ex)
{
// display friendly dialog explaining what went wrong
}
what exception(s) should I put in place of the question mark in the code? It is kind of hard to actually test situations like this when everything is working smoothly and I have no control over the external part, so some insight would be appreciated.
Thanks!
The first thing to do is take advantage of the .Faulted event on your proxy, which you can wire up like this:
((ICommunicationObject)client).Faulted += new EventHandler(client_Faulted);
In your client_Faulted event handler you can then try re-connecting, or shifting to a backup server, or disabling the UI, logging the error, or displaying a message there.
It's obviously still good practice to wrap each call in a try-catch as well, but the .Faulted event can let you deal with most channel problems even earlier.
As for the exception itself, you can have your service throw a FaultException that gets passed back to the client with the details you provide. See an example of its use at this blog posting.
You won't get a FaultException if the channel itself fails (FaultException is a way for the server to communicate its own internal faults to the client).
For channel faults, you may get a CommunicationException or TimeoutException.
Finally, take a look at this project on Codeplex for generating Exception Handling WCF proxies. It may give you a more flexible way of handing faults.
It's not really the client's job to provide as much detail as possible. The maximum amount you really have to provide at the client side is as much as you get back in your exception.
var userName = "bob";
try
{
client.MyWebService(userName);
}
catch(Exception ex)
{
//Maybe we know WellKnownExceptions and can provide Foo advice:
if (ex is WellKnownException)
{
Console.WriteLine("WellKnownException encountered, do Foo to fix Bar.");
}
//otherwise, this is the best you can do:
Console.WriteLine(string.Format(
"MyWebService call failed for {0}. Details: {1}", userName, ex));
}
I was asking the same question, as I have to implement some exception handling on web services calls at my client application, so I ended up here. Although it's an old question, I'd like to give my two cents, updating it a little bit.
The answer given by C. Lawrence Wenham was already very good and points to some interesting information, although the blog link is broken and Codeplex is now archived.
I found those articles very valuables:
Sending and Receiving Faults
https://learn.microsoft.com/en-us/dotnet/framework/wcf/sending-and-receiving-faults
Expected Exceptions
https://learn.microsoft.com/en-us/dotnet/framework/wcf/samples/expected-exceptions
And this article from Michèle Leroux Bustamante (apparently the creator of the Exception Handling WCF Proxy Generator CodePlex project) is very insighful also:
An Elegant Exception-Handling Proxy Solution
http://www.itprotoday.com/microsoft-visual-studio/elegant-exception-handling-proxy-solution
I'm still studying the subject but I guess I'll use a lot of ideias from Michèle. I'm just a little bit concerned about using reflection to call the web service's methods, but I wonder if this would have any impact in such kind of operation, that is inherently slow already.
Just to answer here explicitly what was asked originally, which are the exceptions that could be tested against a web service call:
string errorMessage = null;
// A class derived from System.ServiceModel.ClientBase.
MyWebService wcfClient = new MyWebService();
try
{
wcfClient.Open();
wcfClient.MyWebServiceMethod();
}
catch (TimeoutException timeEx)
{
// The service operation timed out.
errorMessage = timeEx.Message;
}
catch (FaultException<ExceptionDetail> declaredFaultEx)
{
// An error on the service, transmitted via declared SOAP
// fault (specified in the contract for an operation).
errorMessage = declaredFaultEx.Detail.Message;
}
catch (FaultException unknownFaultEx)
{
// An error on the service, transmitted via undeclared SOAP
// fault (not specified in the contract for an operation).
errorMessage = unknownFaultEx.Message;
}
catch (CommunicationException commEx)
{
// A communication error in either the service or client application.
errorMessage = commEx.Message;
}
finally
{
if (wcfClient.State == CommunicationState.Faulted)
wcfClient.Abort();
else
wcfClient.Close();
}
As stated by the articles, the order the exceptions are catched is important, since FaultException<TDetail> derives from FaultException, and FaultException derives from CommunicationException.

Categories

Resources