1

I have a mobile app who consumes a api service. I have a class to manage all the operations (get, post, put) who throws exceptions if the result is not 200.

The app was originaly designed to be mostly offline so my services where like this:

        public async Task<bool> GetMailList(int idUser)
        {
            try
            {
                string uri = GlobalSettings.Instance.MailEndpoint + idUser;
                List<MailDto> listaMailDto = await _requestProvider.GetAsync<List<MailDto>>(uri);                    
                await StoreListMailToDB(MapperMail.MapMailList(listaMailDto));
                return true;
            }
            catch (ServiceAuthenticationException ex) 
            {
                Log.CreateErrorLog("Service.35 - ServiceAuthenticationException \n" + ex.ToString());
                DependencyService.Get<IDialogs>().ShowMessage(AppResources.errorBadUser);
                return false;
            }
            catch (HttpRequestExceptionEx ex)
            {
                Log.CreateErrorLog("Service.40 - HttpRequestExceptionEx \n" + ex.ToString());
                DependencyService.Get<IDialogs>().ShowMessage(AppResources.errorNoConection);
                return false;
            }
            catch(Exception ex)
            {
                Log.CreateErrorLog("Service.45 - Exception \n" + ex.ToString());
                DependencyService.Get<IDialogs>().ShowMessage(AppResources.error);
                return false;
            }
        }

So the service gets the data, and stores it to Sqlite. If was all ok I return true, if no I return false. And in the screen I call to Sqlite to retrieve the data.

The problem comes now because we want to change it to a mostly online app. I want to keep the structure where the services manages the exception getting the data when the function ends. I want something like this but I don't want to return nulls

  public async Task<List<MailDto>> GetMailList(int idUser)
        {
            try
            {
                string uri = GlobalSettings.Instance.MailEndpoint + idUser;
                List<MailDto> listaMailDto = await _requestProvider.GetAsync<List<MailDto>>(uri);  
                List<MailBo> listMappead = MapperMail.MapMailList(listaMailDto)                 
                StoreListMailToDB(listMappead);
                return listMappead;
            }
            catch (ServiceAuthenticationException ex) 
            {
                Log.CreateErrorLog("Service.35 - ServiceAuthenticationException \n" + ex.ToString());
                DependencyService.Get<IDialogs>().ShowMessage(AppResources.errorBadUser);
                return null;
            }
            catch (HttpRequestExceptionEx ex)
            {
                Log.CreateErrorLog("Service.40 - HttpRequestExceptionEx \n" + ex.ToString());
                DependencyService.Get<IDialogs>().ShowMessage(AppResources.errorNoConection);
                return null;
            }
            catch(Exception ex)
            {
                Log.CreateErrorLog("Service.45 - Exception \n" + ex.ToString());
                DependencyService.Get<IDialogs>().ShowMessage(AppResources.error);
                return null;
            }
        }

Any idea?

  • please clarify. you don't return null atm – Ewan Mar 13 '18 at 12:28
  • I added the solution I can do who return nulls – Mulflar Mar 13 '18 at 12:39
  • so what do you want to return when there is nothing to return? – Ewan Mar 13 '18 at 12:40
  • I want a solution to have the services "like" this, but I don't want to return nulls. For example I was thinking on use cancelation Token, cancel the task on exception and Check if the task was succefull – Mulflar Mar 13 '18 at 12:42
  • that's the same as your first code which returns bool – Ewan Mar 13 '18 at 12:51
1

Best practice when calling services and they fail is to throw exceptions and let them bubble up.

  • also: don't use global variables
  • also: don't reference your DI container directly

eg:

public async Task<List<MailDto>> GetMailList(int idUser)
{
    string uri = this.MailEndpoint + idUser;
    var data =  await _requestProvider.GetAsync<List<MailDto>>(uri); 
    return this.mapper.MapMailList(data);
}

async Task MyAppButton_click()
{
    try 
    {
        var data = await this.service.GetMailList(this.userId);
        await this.localRepo.StoreListMailToDB(data)
        mailControl.Data = data;

    }
    catch(Exception ex)
    {
        Log.CreateErrorLog("Service.45 - Exception \n" + ex.ToString());
        this.Dialogs.ShowMessage(ex.Message);
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.