title: Error in Updating a Row using the Mobile Client in Azure Mobile App
body: <p>Need to add an edit function in the mobile app we've created.</p>
  
  <p>We used code from this <a href="https://shellmonger.com/2016/05/04/30-days-of-zumo-v2-azure-mobile-apps-day-16-offline-sync-net-edition/" rel="nofollow noreferrer">blog post</a> to resolve version conflicts (i.e. the client's version is always taken).</p>
  
  <p>However, the edit function would sometimes work and would also, most of the times, result to an error. One time the data in the server was updated but an impending operation was still left in the mobile client. </p>
  
  <p>We've taken a look at the exception in the client and the message was just "Error has occurred." Also taken a look at the server analytics and the result code is 500.</p>
  
  <p><strong>I've got three questions:</strong></p>
  
  <ol>
  <li>Why is the update operation resulting to an error?</li>
  <li>Are there other ways in debugging the error either in the client or server? Error 500 is very general and "Error has occurred" is not very helpful.</li>
  <li>Is it possible that the client can create a Sale and upload it into the server even if there is a discrepancy between the Sale model in the server and corresponding sql database?</li>
  </ol>
  
  <p><strong>Update</strong></p>
  
  <p>Turned on logging in the server, changed PatchSale to async so that we can await UpdateAsync(id, patch), and put a try-catch where await UpdateAsync is called.</p>
  
  <p>Here's what was logged in the catch area:</p>
  
  <pre><code>CATCH:
  Helplink
  
  Message
  Processing of the HTTP request resulted in an exception. Please see the HTTP response returned by the 'Response' property of this exception for details.
  StackTrace
  at Microsoft.Azure.Mobile.Server.Tables.EntityUtils.&lt;SubmitChangesAsync&gt;d__0.MoveNext()
  --- End of stack trace from previous location where exception was thrown ---
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     at Microsoft.Azure.Mobile.Server.EntityDomainManager`1.&lt;UpdateAsync&gt;d__10.MoveNext()
  --- End of stack trace from previous location where exception was thrown ---
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     at Microsoft.Azure.Mobile.Server.EntityDomainManager`1.&lt;UpdateAsync&gt;d__3.MoveNext()
  --- End of stack trace from previous location where exception was thrown ---
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     at Microsoft.Azure.Mobile.Server.TableController`1.&lt;PatchAsync&gt;d__12.MoveNext()
  --- End of stack trace from previous location where exception was thrown ---
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     at SynthesisServer.Controllers.SaleController.&lt;PatchSale&gt;d__3.MoveNext()
  Source
  Microsoft.Azure.Mobile.Server.Entity
  </code></pre>
  
  <p>AdrianHall suspected that there might be a discrepancy between the Sale Model in the .NET server and its corresponding SQL server. i've compared the two and can't seem to find any difference (i assume that Id, Version, CreatedAt, UpdatedAt, and Deleted are included when extending EntityData). Further, if there is a difference between the model in the .NET server and SQL server how is it possible that can we create a Sale and upload it to the server?</p>
  
  <p>Also, posted the Sale Model in the server below and the columns in the SQL server.</p>
  
  <p>Here's the code for reference:</p>
  
  <p><strong>Server: Update method in the controller</strong></p>
  
  <pre><code>public Task&lt;Sale&gt; PatchSale(string id, Delta&lt;Sale&gt; patch)
  {
      System.Diagnostics.Trace.TraceInformation("INSIDE PATCH SALE!!!");
  
      return UpdateAsync(id, patch);
  }
  </code></pre>
  
  <p><strong>Mobile Client: Updating Sale</strong></p>
  
  <pre><code>public async Task&lt;Sale&gt; UpdateSaleAsync(Sale sale)
  {
    await saleTable.UpdateAsync(sale);
    return sale;
  }
  </code></pre>
  
  <p><strong>Mobile Client: Syncing Sale</strong></p>
  
  <pre><code>public async Task&lt;bool&gt; SyncSalesAsync()
  {
      bool wasPushed = true;
  
      try
      {
          // Sync data with cloud
          await MobileService.SyncContext.PushAsync();
          await saleTable.PullAsync("allSales", saleTable.CreateQuery());
      }
      catch (MobileServicePreconditionFailedException&lt;Sale&gt; conflict)
      {
          Console.WriteLine($"taskTitle_Changed - Conflict Resolution for item ${conflict.Item.Id}");
      }
      catch (MobileServicePushFailedException exc)
      {
          Console.WriteLine("Sync Sales MSPFE Exception: ");
          Console.WriteLine("/////////////////////");
          Console.WriteLine("Message:");
          Console.WriteLine(exc.Message);
          Console.WriteLine("HelpLink:");
          Console.WriteLine(exc.HelpLink);
          Console.WriteLine("Source:");
          Console.WriteLine(exc.Source);
          Console.WriteLine("Stack Trace:");
          Console.WriteLine(exc.StackTrace);
          Console.WriteLine("/////////////////////");
  
          if (exc.PushResult != null)
          {
              var c = 1;
  
              foreach (var i in exc.PushResult.Errors)
              {
                  Console.WriteLine("Inside push Details: " + c);
                  Console.WriteLine("Handled: ");
                  Console.WriteLine(i.Handled);
                  Console.WriteLine("Item");
                  Console.WriteLine(i.Item);
                  Console.WriteLine("O Kind");
                  Console.WriteLine(i.OperationKind);
                  Console.WriteLine("Status");
                  Console.WriteLine(i.Status);
                  Console.WriteLine("Table Name");
                  Console.WriteLine(i.TableName);
                  Console.WriteLine("Raw Result");
                  Console.WriteLine(i.RawResult);
                  Console.WriteLine("Result");
                  Console.WriteLine(i.Result);
                  Console.WriteLine("Item");
                  Console.WriteLine(i.Item);
                  c++;
  
                  Console.WriteLine("Cast Result to Sale");
                  var serverItem = i.Result.ToObject&lt;Sale&gt;();
                  Console.WriteLine("Cast Item to Sale");
                  var localItem = i.Item.ToObject&lt;Sale&gt;();
  
                  if (serverItem.Equals(localItem))
                  {
                      Console.WriteLine("server item equals");
                      // Items are the same, so ignore the conflict
                      await i.CancelAndDiscardItemAsync();
                  }
                  else
                  {
                      Console.WriteLine("else");
                      Console.WriteLine("localitem version: " + localItem.Version);
                      Console.WriteLine("serveritem version: " + serverItem.Version);
                      // Always take the client
                      localItem.Version = serverItem.Version ?? localItem.Version;
  
                      var item = JObject.FromObject(localItem);
                      Console.WriteLine("item from jobject");
                      Console.WriteLine(item);
                      try
                      {
                          await i.UpdateOperationAsync(item);
                      }
                      catch (Exception e)
                      {
                          Console.WriteLine("Else Message Error");
                          Console.WriteLine(e.Message);
                          Console.WriteLine("Else Stack Trace");
                          Console.WriteLine(e.StackTrace);
  
                      } 
                  }
              }
          }
          return false;
      }
  
      catch (MobileServiceInvalidOperationException msioe)
      {
          Console.WriteLine("Sync Sales MSIOE Exception: ");
          Console.WriteLine("/////////////////////");
          Console.WriteLine(msioe.Message);
          Console.WriteLine("----");
          Console.WriteLine(msioe.HelpLink);
          Console.WriteLine("----");
          Console.WriteLine(msioe.Source);
          Console.WriteLine("----");
          Console.WriteLine(msioe.StackTrace);
          return false;
      }
      catch (Exception e)
      {
          Console.WriteLine("Sync Sales General Exception: ");
          Console.WriteLine("/////////////////////");
          Console.WriteLine(e.Message);
          Console.WriteLine("----");
          Console.WriteLine(e.HelpLink);
          Console.WriteLine("----");
          Console.WriteLine(e.Source);
          Console.WriteLine("----");
          Console.WriteLine(e.StackTrace);
          return false;
      }
  
      return wasPushed;
  }
  </code></pre>
  
  <p><strong>Mobile Client: Sale Model</strong></p>
  
  <pre><code>public class Sale
      {
          [JsonProperty(PropertyName = "id")]
          public string Id { get; set; }
  
          [JsonProperty(PropertyName = "productId")]
          public string ProductId { get; set; }
  
          [JsonProperty(PropertyName = "promoterId")]
          public string PromoterId { get; set; }
  
          [JsonProperty(PropertyName = "storeId")]
          public string StoreId { get; set; }
  
          [JsonProperty(PropertyName = "paymentMethodId")]
          public string PaymentMethodId { get; set; }
  
          [JsonProperty(PropertyName = "corporateSale")]
          public bool CorporateSale { get; set; }
  
          [JsonProperty(PropertyName = "dateSold")]
          public DateTime? DateSold { get; set; }
  
          [JsonProperty(PropertyName = "priceSold")]
          public double PriceSold { get; set; }
  
          [JsonProperty(PropertyName = "quantitySold")]
          public int QuantitySold { get; set; }
  
          [JsonProperty(PropertyName = "remarks")]
          public string Remarks { get; set; }
  
          [JsonProperty(PropertyName = "deleted")]
          public bool Deleted { get; set; }
  
          [JsonProperty(PropertyName = "createdAt")]
          public DateTime CreatedAt { get; set; }
  
          [JsonProperty(PropertyName = "updatedAt")]
          public DateTime UpdatedAt { get; set; }
  
          [JsonProperty(PropertyName = "version")]
          public string Version { get; set; }
  
          [JsonProperty(PropertyName = "saleTransactionId")]
          public string SaleTransactionId { get; set; }
  
          [JsonIgnore]
          public virtual Dictionary&lt;string, string&gt; Data
          {
              get
              {
                  var data = new Dictionary&lt;string, string&gt;
                  {
                      ["Id"] = Id,
                      ["ProductId"] = ProductId,
                      ["PromoterId"] = PromoterId,
                      ["StoreId"] = StoreId,
                      ["PaymentMethodId"] = StoreId,
                      ["CorporateSale"] = CorporateSale.ToString(),
                      ["DateSold"] = "",
                      ["PriceSold"] = PriceSold.ToString(),
                      ["QuantitySold"] = QuantitySold.ToString(),
                      ["Remarks"] = Remarks,
                      ["SaleTransactionId"] = SaleTransactionId,
                      ["Deleted"] = Deleted.ToString(),
                      ["CreatedAt"] = CreatedAt.ToString(),
                      ["UpdatedAt"] = UpdatedAt.ToString(),
                      ["Version"] = Version
                  };
  
                  if (DateSold != null) data["DateSold"] = ((DateTime)DateSold).ToString();
  
                  return data;
              }
  
          }
  
          [JsonIgnore]
          public bool IsNew
          {
              get
              {
                  return string.IsNullOrEmpty(PromoterId) || UpdatedAt == null || CreatedAt == null || string.IsNullOrEmpty(Version);
              }
          }
  
          public virtual Product Product { get; set;}
          public virtual Store Store { get; set; }
          public virtual PaymentMethod PaymentMethod { get; set; }
  
          // Default constructor
          public Sale() {}
  
          public Sale(Dictionary&lt;String, String&gt; data)
          {
              DateSold = DateTime.Parse(data["DateSold"]);
              CorporateSale = bool.Parse(data["CorporateSale"]);
              ProductId = data["ProductId"];
              PriceSold = Double.Parse(data["PriceSold"]);
              QuantitySold = int.Parse(data["QuantitySold"]);
              StoreId = data["StoreId"];
              PaymentMethodId = data["PaymentMethodId"];
              Remarks = data["Remarks"];
  
              SaleTransactionId = Guid.NewGuid().ToString();
          }
  
          public virtual string TransactionId()
          {
              string value = "Not Synced";
  
              if (!string.IsNullOrEmpty(SaleTransactionId)) value = SaleTransactionId;
  
              return value;
          }
  
          public override string ToString()
          {
              return "I'm a Sale: DateSold " + DateSold + " ProductID " + ProductId + " StoreID " + StoreId + " Corporate Sale " + CorporateSale;
          }
  
          public virtual string FormattedCorporateSale()
          {
              string result = "No";
  
              if (CorporateSale) result = "Yes";
  
              return result;
          }
  
          public virtual string FormattedDateSold ()
          {
              if (DateSold == null) return "DateSold not recorded";
  
              // Convert DateSold from DateTime? to DateTime cos DateTime? doesn't have the ToString with overload for 
              // formatting
              DateTime date = (DateTime)DateSold;
  
              return date.ToString("dd MMM yyyy") + " " + date.ToString("ddd");
          }
  
          public virtual string FormattedPriceSold()
          {
              return string.Format("{0:n}", PriceSold);
          }
  
          public virtual string FormattedPriceSoldForIndex()
          {
              return string.Format("{0:n}", PriceSold);
          }
  
          public virtual string FormattedQuantitySold()
          {
              string formattedQuantitySold = QuantitySold.ToString () + " unit";
  
              if (QuantitySold &gt; 1) formattedQuantitySold = formattedQuantitySold + "s";
  
              return formattedQuantitySold;
          }
  
          public virtual string FormattedQuantitySoldForIndex()
          {
              string formattedQuantitySold = QuantitySold.ToString() + " unit";
  
              if (QuantitySold &gt; 1) formattedQuantitySold = formattedQuantitySold + "s";
  
              return formattedQuantitySold;
          }
  
          public virtual string FormattedRemarks()
          {
              string result = "none";
  
              if (!(String.IsNullOrEmpty(Remarks))) result = Remarks;
  
              return result;
          }
  
          public virtual string FormattedProductSku()
          {
              return "Im a regular sale";
          }
  
          public virtual string FormattedProductSkuForIndex()
          {
              return "Im a regular sale";
          }
  
          public virtual string FormattedProductPartNumber()
          {
              return "I'm a regualr sale";
          }
  
          public virtual string FormattedStoreName()
          {
              return "I'm a regular sale";
          }
  
          public virtual string FormattedPaymentMethodName()
          {
              return "I'm a regular sale";
          }
  
          public virtual bool IsNoSale()
          {
              throw new NotImplementedException();
          }
  
          // Updates only those properties that are on the form
          public virtual void Update(Dictionary&lt;string, string&gt; data)
          {
              DateSold = DateTime.Parse(data["DateSold"]);
              CorporateSale = bool.Parse(data["CorporateSale"]);
              ProductId = data["ProductId"];
              PriceSold = Double.Parse(data["PriceSold"]);
              QuantitySold = int.Parse(data["QuantitySold"]);
              StoreId = data["StoreId"];
              PaymentMethodId = data["PaymentMethodId"];
              Remarks = data["Remarks"];
          }
      }
  </code></pre>
  
  <p><strong>Server: Sale Model</strong></p>
  
  <pre><code>[Table("sales.Sales")]
  public class Sale : EntityData
  {
      public string PromoterId { get; set; }
      public DateTime DateSold { get; set; }
      [Range(1, Int32.MaxValue, ErrorMessage = "Quantity Sold must be &gt; 0")]
      public int QuantitySold { get; set; }
      [Range (1, Double.MaxValue, ErrorMessage = "Price Sold must be &gt; 0")]
      public double PriceSold { get; set; }
      public bool CorporateSale { get; set; }
  
      [StringLength(255)]
      public string Remarks { get; set; }
  
      public string ProductId { get; set; }
      public string StoreId { get; set; }
      public string PaymentMethodId { get; set; }
      public string SaleTransactionId { get; set; }
  
      public virtual Product Product { get; set; }
      public virtual Store Store { get; set; }
      public virtual PaymentMethod PaymentMethod { get; set; }
      [NotMapped, JsonIgnore]
      public virtual Promoter Promoter { get; set; }
  
      [NotMapped]
      public string DateUploaded
      {
          get
          {
              string date = "";
  
              if (CreatedAt != null)
              {
                  var transformed = CreatedAt.GetValueOrDefault();
                  date = transformed.ToString("yyyy-MMM-dd");
              }
  
              return date;
          }
  
          set
          {
  
          }
      }
  
      [NotMapped]
      public string DateSold_String
      {
          get
          {
              string date = "";
  
              if (DateSold != null)
              {
                  var transformed = DateSold;
                  date = transformed.ToString("yyyy-MMM-dd");
              }
  
              return date;
          }
  
          set
          {
  
          }
      }
  
      public override string ToString()
      {
          var message = "I'm a Sale! DateSold: ";
  
          if (DateSold != null) message = message + DateSold;
          else message = message + "x";
  
          if (String.IsNullOrEmpty(ProductId)) message = message + " ProductID: " + "x";
          else message = message + " ProductID: " + ProductId;
  
          if (String.IsNullOrEmpty(StoreId)) message = message + " StoreID: " + "x"; 
          else message = message + " StoreID: " + StoreId;
  
          if (String.IsNullOrEmpty(PromoterId)) message = message + " PromoterID: " + "x";
          else message = message + " PromoterID: " + PromoterId;
  
          return message;
      }
  }
  </code></pre>
  
  <p><strong>SQL Server: Sale Columns</strong> (dunno what else to show aside from the columns)</p>
  
  <pre><code>Id(PK, nvarchar(128), not null)
  PromoterId(nvarchar(max), null)
  DateSold(datetime, not null)
  QuantitySold(int, not null)
  PriceSold(float, not null)
  CorporateSale(bit, not null)
  Remarks(nvarchar(255), null)
  ProductId(FK, nvarchar(128), null)
  StoreId(FK, nvarchar(128), null)
  PaymentMethodId(FK, nvarchar(128), null)
  SaleTransactionId(nvarchar(max), null)
  Version(timestamp, not null)
  CreatedAt(datetimeoffset(7), not null)
  UpdatedAt(datetimeoffset(7), null)
  Deleted(bit, not null)
  </code></pre>