0

I have very basic fundamental doubt regarding asynchronous Web API programming. I want to make call to SaveCaseSearch in my controller asynchronously. But the call passes through various layers of DAL and eventually calls DB.

Should those consecutive calls also be made asynchronous ?

I am very new to the world of async so I might already have made some mistakes. Just correct me if anything seems wrong.

So for the controller , I am doing something like the below :

/*Create API for Case*/
[HttpPost]
[Route("createcase")]
public IHttpActionResult PostCreateCase([FromBody]  ARC.Donor.Business.Case.CreateCaseInput CreateCaseInput)
{
    ARC.Donor.Service.Case.CaseServices cs = new ARC.Donor.Service.Case.CaseServices();
    var searchResults = cs.createCase(CreateCaseInput);
    List<CreateCaseOutput> searchOutputResults = (List<CreateCaseOutput>)searchResults;
    if (!string.IsNullOrEmpty(searchOutputResults.ElementAt(0).o_case_seq.ToString()))
       SaveCaseSearchDetails(SaveSearchInput); /*This should be called asynchronously*/
    return Ok(searchResults);
}

This

SaveCaseSearchDetails

now needs to be called in async mode . So I have written :

[HttpPost]
public async Task<IHttpActionResult> SaveCaseSearchDetails([FromBody]  ARC.Donor.Business.SaveSearchInput SaveSearchInput)
{
    ARC.Donor.Service.Case.CaseServices cs = new ARC.Donor.Service.Case.CaseServices();
    var searchResults = await cs.saveCaseSearchDetails(SaveSearchInput);
}

Then if that is correct

should the consecutive calls be async too ?

For now they are

public IList<Entities.Case.SaveCaseSearchOutput> saveCaseSearch(ARC.Donor.Data.Entities.Case.SaveCaseSearchInput SaveCaseSearchInput)
{
    Repository rep = new Repository();
    string strSPQuery = string.Empty;
    List<object> listParam = new List<object>();
    SQL.CaseSQL.getCreateCaseParameters(SaveCaseSearchInput, out strSPQuery, out listParam);
    var AcctLst = rep.ExecuteStoredProcedure<Entities.Case.SaveCaseSearchOutput>(strSPQuery, listParam).ToList();
    return AcctLst;
}

Is

SQL.CaseSQL.getCreateCaseParameters

method needs to be called in async manner ? But in that case the immediate next line

rep.ExecuteStoredProcedure

can't execute successfully right ? Because strSPQuery comes from the previous line itself ?

I am thinking in a wrong way ? Please correct me .

3
  • 1
    Should those consecutive calls also be made asynchronous ? Yes, if you want "true" async functionality. Commented Apr 12, 2016 at 6:21
  • But in that case , as in the last case I have depicted , it will break right ? Commented Apr 12, 2016 at 6:31
  • What do you expect "asynchronous" to do ? Unless the blocking operations are themselves asynchronous, you'll still need to block a thread to run them. Commented Apr 12, 2016 at 8:44

2 Answers 2

6

Should those consecutive calls also be made asynchronous?

Yes.

SaveCaseSearchDetails now needs to be called in async mode

That's the hard way of doing it.

A much more natural approach is to start at the other end. Whatever part of your code is actually executing the database query should be made asynchronous first. Then you call it using await, which makes those methods async, so they should be called with await, etc., until you finally reach your controller action which is the last thing to be made asynchronous.

actually the problem I am facing is SaveCaseSearchDetails(SaveSearchInput) in PostCaseCreate method needs to be called somewhat async because we don't want to wait for return Ok(searchResults)

Ah, that's a totally different question. You want to return early. Async will not help you do this; as I explain on my blog (and in an MSDN article on async ASP.NET), async does not change the HTTP protocol.

There are a few approaches to returning early or "fire and forget" on ASP.NET that I describe on my blog. However, ASP.NET was not designed for this scenario, so you need to tread carefully. The only fully reliable solution is a properly distributed architecture.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the insight. But SQL.CaseSQL.getCreateCaseParameters(SaveCaseSearchInput, out strSPQuery, out listParam); var AcctLst = rep.ExecuteStoredProcedure<Entities.Case.SaveCaseSearchOutput>(strSPQuery, listParam).ToList(); the first line contains out keyword which is not supported by await I suppose . And the immediate line uses the out keyword result. How to achieve that using async/await approach?
@StrugglingCoder: You're still approaching this from the wrong direction. If getCreateCaseParameters doesn't talk to the db (which is likely), then you'll never need to make it async. If it does, then you just need to return two values.
1

You cannot call SQL.CaseSQL.getCreateCaseParameters in an async manner (with await) since it uses the out keyword which isn't available for async metods.

If you want your DB call to happen async you'll have to find a DB method that you can await. Then you can change the saveCaseSearch method to also be async and await it from your controller method.

7 Comments

For now I dont wanna break my existing service and DAL layer functionalities. So can I keep them synchronous ? Or is it against async topology and will cause performance problem in my application ?
If an async method does not have an 'await' in it, it will run synchronously so nothing unexpected should happen. Your IDE might warn you, but thats about it. (Note that making your controller method async is pointless in that case, and you might as well make it synchronous)
@StrugglingCoder if you want async, you have to break your synchronous DAL and add asynchronous methods that end up making real asynchronous database calls, eg calling ExecuteReaderAsync instead of ExecuteReader. Otherwise you'll end up blocking a thread - either the original or some other you start with Task.Run. You won't get any of the benefits but you'll pay an extra overhead
No, the problem you are facing is that you have a synchronous layer that you want to call "asynchronously". This doesn't even make sense though - what's the point of releasing the original thread if you are going to block another thread? You are still wasting a thread, but add an overhead for the switch. An asynchronous DAL call though, would release the original thread completely while waiting for a database reaponse without using a new thread.
@StrugglingCoder what do you expect to gain from making the controller asynchronous, if you don't want to convert the blocking operations into asynchronous ones? Perhaps you misunderstand what "asynchronous" means in a Web application (not just Web API)?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.