I'm responsible for maintaining a web service project in c#. I have one service class with a bunch of methods that look a lot like this:
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "v1/Login", ResponseFormat = WebMessageFormat.Json)]
public string Login()
{
try
{
JObject incomingRequestJson = retrieveJson();
JObject returningJson = new JObject();
string accountId = incomingRequestJson.SelectToken("accountId", true).ToString();
string username = incomingRequestJson.SelectToken("userName", true).ToString();
string password = incomingRequestJson.SelectToken("password", true).ToString();
LoginResult result = readerBLL.Login(accountId, username, password);
returningJson.Add(new JProperty("userSessionId", result.userSessionId));
returningJson.Add(new JProperty("friendlyUserName", result.friendlyUserName));
return returningJson.ToString(Newtonsoft.Json.Formatting.None);
}
catch (Exception ex)
{
throw new WebFaultException<string>(ex.Message.ToString(), HttpStatusCode.OK);
}
}
Note that retrieveJson()
grabs a JSON string from the HttpContext
and runs JObject.Parse()
on it.
Note also that the consumer of this service is a Flex app, so I do need the WebFaultException business with the "OK" response code (The networking component in Flex treats connection timeouts and all HTTP error codes exactly the same - no further data other than
I don't like the way I have the try-catch
block repeated in every method, so I tried making the following method:
private object invokeBusinessLogic(Func<JObject, object> f)
{
try
{
return f(retrieveJson());
}
catch (Exception ex)
{
WebFaultException<string> wfe = new WebFaultException<string>(ex.Message.ToString(), HttpStatusCode.OK);
throw wfe;
}
}
Then my service methods can look like this:
public object Login()
{
LoginResult result = (LoginResult) invokeBusinessLogic(readerBLL.Login);
returningJson.Add(new JProperty("userSessionId", result.userSessionId));
returningJson.Add(new JProperty("friendlyUserName", result.friendlyUserName));
return returningJson.ToString(Newtonsoft.Json.Formatting.None);
}
However, this has the problem that the use of JSON to carry the request data gets exposed to the business layer. Is there a better way to avoid the duplicate try-catch
blocks than this invokeBusinessLogic
idea?
public LoginResult Login()
in the service layer -- and that would break my clients. The current code actually sends an escaped string rather than a real JSON string :/ – Brian Jan 2 '14 at 22:03