Search code examples
uwpasp.net-web-api2httprequesthttpclientbson

how to update local database by service?


I try to update local database in UWP app by WEB API service. I need send list of existing entity ID to Web service and get other entity from service.

my model

public class LibraryCategoryModel
{
    public int ID { get; set; }
    public string CategoryTitle { get; set; }
    public byte[] Picture { get; set; }
}

and my controller in web api

 // GET: api/Category
    public IQueryable<LibraryCategoryModel> GetLibraryCategoryModels(HttpRequestMessage request)
    {
        var string1 = request.Content.ReadAsStringAsync();
        List<int> existingIdCategoryList = new List<int>();
        existingIdCategoryList = JsonConvert.DeserializeObject<List<int>>(string1.Result);
        var entityList = db.LibraryCategoryModels.ToList();
        foreach (var Id in existingIdCategoryList)
        {
            entityList = entityList.Where(item => item.ID != Id).ToList();
        }
        return entityList as IQueryable<LibraryCategoryModel>;
    }

and my request

 private async void LoadDataFromNetwork(List<int> CategoryIdList)
    {
        if (NetworkHelper.IsInternet() || NetworkHelper.HasInternet())
        {
            using (HttpClient client = new HttpClient())
            {
                client.BaseAddress = new Uri(serviceUrl);
                // Set requast
                using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "Api/Category"))
                {
                    // Set the Accept header for BSON.
                    request.Headers.Accept.Clear();
                    request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/bson"));
                    string Content = await Task.Factory.StartNew(() => JsonConvert.SerializeObject(CategoryIdList));
                    request.Content = new StringContent(Content, System.Text.Encoding.UTF8, "application/json");
                    var response = await client.SendAsync(request);
                    response.EnsureSuccessStatusCode();
                    // Use BSON formatter to deserialize the result.
                    MediaTypeFormatter[] formatters = new MediaTypeFormatter[] { new BsonMediaTypeFormatter() };
                    try
                    {
                        var newCategorys = await response.Content.ReadAsAsync<LibraryCategoryModel[]>(formatters);
                        foreach (var category in newCategorys)
                        {
                            _dataService.InsertCategory(category);
                            AllCategoryList.Add(new LibraryCategoryViewModel(category));
                            _newCategoryIdListFromNetWork.Add(category.ID);
                        }
                    }
                    catch (Exception)
                    {

                        throw;
                    }

                }

            }
        }
    }

this work for me but i do not Sure this way is proper and best solution. please guide me.


Solution

  • First off, if it works and there are no specific issues you're encountering then it may be good enough.
    There are lots of ways this could potentially be improved but definitions of a "proper way" or "best solution" will always be opinion based.

    That said, here are some suggestions:

    • Including "Model" in LibraryCategoryModel is redundant. I'd remove it.
    • Does your API need to return an IQueryable? Or would IEnumerable, or even IList be sufficient? - always keep it as simple as necessary.
    • string1 is a poor name for a variable as it has no meaning. Use something that describes what it holds, such as requestContent.
    • Have your API method take a List<int> directly then you can do away with needing to handle any unexpected input.
    • Handle unexpected, invalid, or missing input to your API method.
    • The logic in your foreach loop in the API could be greatly simplified so that the result needs only setting once, rather than making new lists for every iteration through the list passed in.
    • Use a single, static HTTPClient instance (see https://skimming.net/why-you-should-reuse-httpclient-instances/)
    • Don't just catch exceptions and then throw an new one. All this does is lose any exception info. At the very least you should be logging exceptions and reporting something back to the user.
    • Your NetworkHelper method names don't clearly distinguish between what they each do. Rename them to make their meaning and differences clearer.
    • Don't just do nothing if a condition, such as connectivity, is not met. Indicate to the user if something is not possible and provide indication of what can be done to rectify an issue or act as an alternative.
    • Throwing an unhandled error is a successful HTTP request is not made is never a good thing to do. There are lots of reasons beyond your control that could mean a successful request may not be possible and just crashing is not the way to deal with them.
    • Alternatively, if handling of request failures is in code separate to the above then it will make maintaining the above code harder.
    • Using different combinations of encoding from your API has the potential to confuse others (or even yourself) in the future. Unless you've got a really good reason for sending JSON but requesting BSON then you should use the same for both.
    • On the assumption that you'll also use them elsewhere, define constants for your content encodings. Avoid magic strings in code--especially ones that are duplicated across a codebase.
    • Remove the comments that document what the code is doing. This should be clear from reading the code. Make the code clearer if need be. Having comments that say what the code is doing can actually be more confusing. Especially if the code ever changes but the comments don't.
    • Awaiting the creation of a Task just to serialize the JSON seems unnecessary. Remove if not definitely needed. (Add document why if it is.)
    • LoadDataFromNetwork does a lot and would probably be more maintainable if split into multiple methods: for creating the request, making the request and handling the response.
    • The plural of "category" is "categories"
    • The processing of the returned categories seems confused. There's what are presumably class level variables and a static list. The _newCategoryIdListFromNetWork variable looks like it should be more closely tied to this method, not the class and any logic relating to it may be overly distributed around the class.