Azure Table Storage, ExecuteBatchAsync, Unexpected response code for operation : 0 - c#

By leveraging the Windows Azure SDK, I try to insert entities using CloudTable.ExecuteBatchAsync and TableBatchOperations.
The entity serialized as Json:
{
"LastAccessDate":"2015-02-27T00:00:00Z",
"Title":"Google open-sources HTTP/2-based RPC framework",
"PublicationDate":"0001-01-01T00:00:00",
"Id":"tag:theregister.co.uk,2005:story/2015/02/27/google_opensources_http2based_rpc_framework/",
"LastUpdatedDate":"2015-02-27T00:00:00Z",
"FeedUrl":"http://www.theregister.co.uk/software/developer/headlines.atom",
"Url":"http://go.theregister.com/feed/www.theregister.co.uk/2015/02/27/google_opensources_http2based_rpc_framework/",
"PartitionKey":"http%3a%2f%2fwww.theregister.co.uk%2fsoftware%2fdeveloper%2fheadlines.atom",
"RowKey":"http%3a%2f%2fgo.theregister.com%2ffeed%2fwww.theregister.co.uk%2f2015%2f02%2f27%2fgoogle_opensources_http2based_rpc_framework%2f",
"Timestamp":"0001-01-01T00:00:00+00:00",
"ETag":null
}
Represented by this POCO entity:
public class SyndicationFeedArticle : TableEntity
{
public virtual DateTime LastAccessDate { get; set; }
public virtual string Title { get; set; }
public virtual DateTime PublicationDate { get; set; }
public virtual string Id { get; set; }
public virtual DateTime LastUpdatedDate { get; set; }
public virtual string FeedUrl { get; set; }
public virtual string Url { get; set; }
}
The problem arises when the entity is constructed from RSS xml processing. ExecuteBatch of inserts throws Unexpected response code for operation : 0. I do understand that it means that the batch operation at index 0 failed. Usually it's a problem with either Partition or Row keys being incorrect such as containing invalid characters (which is not the case above) or exceeding 1kb in size which in this case doesn't apply.
Here's what puzzling me:
Both unit test and business code entities (although constructed differently) generate the exact same Json serialization data
Both processes (manual new() creation and RSS business code) works well in a Unit test
There is no issue at all when storing on the Emulator, it fails in Azure Cloud only.
What I'm looking for are pointers on how I could troubleshoot this issue. I've recreated various scenarios in unit tests and made sure my entities don't break constraints on keys but no luck. My main issue is why can't I get constant behaviours between the emulator and the cloud. This would really help me out or at least, it would point me toward another way to fix this problem.
Thanks!

Ok, got it figured out.
What happens in this particular scenario:
PublicationDate is instantiated using a DateTimeOffset.Date as source value which may be set at MinValue. The table storage doesn't support MinValue for a DateTime column.
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<code>OutOfRangeInput</code>
<message xml:lang="en-US">One of the request inputs is out of range. RequestId:9e74bf7a-0002-004e-1142-16dabb000000 Time:2015-02-28T02:01:42.2124803Z</message>
</error>
I changed the entity property for a DateTime? and manages this as a business rule. Of course, I'm left wondering why locally on the emulator this is supported...

Related

Using a REST Api, how to include "any kind of json" in my typed request model?

I am using .NET Framework and ASP.NET Core to create a REST web Api.
This web api has a call that gets a request model to save data and some call that later retrieves the data.
Most of the data is structured information I need in the backend and it is saved into different fields and tables in the database. On retrieval it is loaded from those tables and returned.
This all works.
However, I now have a requirement where the caller wants to save and later retrieve arbitrary data (lets just say a random json) as one of those fields. I can save and load json from the database that is not a problem, my problem is to build the web api model for my request.
[HttpPost]
public IActionResult Save([FromBody] ApiCallRequestModel request)
{
// ...
}
public sealed class ApiCallRequestModel
{
// structured, well known information
public int? MaybeSomeNumber { get; set; }
[Required]
public string SomeText { get; set; }
[Required]
public SubModel SomeData { get; set; }
// one field of unknown json data
public ??? CustomData { get; set; }
}
I could think of dynamic or maybe even ExpandoObject or JObject to try and I might, but I would like a solution that works because it's best practice, not just because I tried and it didn't fail today with my simple tests.
If everything else fails, I could just make the field a string and tell the client to put serialized json into it. But that's a workaround I would see as a last resort if this question yields no answers.
It has proven to be extremly hard to google this topic, since all words I would use lead me to pages explaining Json serialization of my request model itself. I know how that works and it's not a problem. The mix of structured data and free json is what I cannot find out from a somewhat authorative source.
So what type would you use here, what is the best practice for receiving arbitrary json in one property of your model?
So to sum this up, as suggested I used a JToken from the Json.NET nuget package, since I already had that package in my project.
[HttpPost]
public IActionResult Save([FromBody] ApiCallRequestModel request)
{
// ...
}
public sealed class ApiCallRequestModel
{
// structured, well known information
public int? MaybeSomeNumber { get; set; }
[Required]
public string SomeText { get; set; }
[Required]
public SubModel SomeData { get; set; }
// one field of unknown json data
public JToken CustomData { get; set; }
}
Works like a charm.

Issue with lambda expressions in c# data retrieval

i'm writing a system to track observation values from sensors (e.g. temperature, wind direction and speed) at different sites. I'm writing it in C# (within VS2015) using a code-first approach. Although i've a reasonable amount of programming experience, I'm relatively new to C# and the code-first approach.
I've defined my classes as below. I've built a REST api to accept observation reading through Post, which has driven my desire to have Sensor keyed by a string rather than an integer - Some sensors have their own unique identifier built in. Otherwise, i'm trying to follow the Microsoft Contoso university example (instructors - courses- enrolments).
What I am trying to achieve is a page for a specific site with a list of the sensors at the site, and their readings. Eventually this page will present the data in graphical form. But for now, i'm just after the raw data.
public class Site
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Sensor> Sensors { get; set; }
}
public class Sensor
{
[Key]
public string SensorName { get; set; }
public int SensorTypeId { get; set; }
public int SiteId { get; set; }
public ICollection<Observation> Observations { get; set; }
}
public class Observation
{
public int Id { get; set; }
public string SensorName { get; set; }
public float ObsValue { get; set; }
public DateTime ObsDateTime { get; set; }
}
and I've created a View Model for the page I'm going to use...
public class SiteDataViewModel
{
public Site Site { get; set; }
public IEnumerable<Sensor> Sensors { get; set;}
public IEnumerable<Observation> Observations { get; set; }
}
and then i try to join up the 3 classes into that View Model in the SiteController.cs...
public actionresult Details()
var viewModel.Site = _context.Sites
.Include(i => i.Sensors.select(c => c.Observations));
i used to get an error about "cannot convert lambda expression to type string", but then I included "using System.Data.Entity;" and the error has changed to two errors... on the 'include', I get "cannot resolve method 'include(lambda expression)'...". And on the 'select' i get "Icollection does not include a definition for select..."
There's probably all sorts of nastiness going on, but if someone could explain where the errors are (and more importantly why they are errors), then I'd be extremely grateful.
Simply you can you use like
viewModel.Site = _context.Sites
.Include("Sensors).Include("Sensors.Observations");
Hope this helps.
The way your ViewModel is setup, you're going to have 3 unrelated sets of data. Sites, sensors, and observations. Sites will have no inherent relation to sensors -- you'll have to manually match them on the foreign key. Realistically, your ViewModel should just be a list of Sites. You want to do
#Model.Sites[0].Sensors[0].Observations[0]
not something convoluted like
var site = #Model.Sites[0]; var sensor = #Model.Sensors.Where(s => SiteId == site.Id).Single(); etc...
Try doing
viewModel.Site = _context.Sites.Include("Sensors.Observations").ToList();
Eager-loading multiple levels of EF Relations can be accomplished in just one line.
One of the errors you reported receiving, by the way, is because you're using 'select' instead of 'Select'
And lastly, be aware that eager-loading like this can produce a huge amount of in-memory data. Consider splitting up your calls for each relation, such that you display a list of Sensors, and clicking, say, a dropdown will call an API that retrieves a list of Sites, etc. This is a bit more streamlined, and it prevents you from getting held up because your page is loading so much information.
Update
I've created a sample application for you that you can browse and look through. Data is populated in the Startup.Configure method, and retrieved in the About.cshtml.cs file and the About.cshtml page.. This produces this page, which is what you're looking for I believe.

Which data types should a client model use for offline sync with the Azure mobile apps SDK?

I am using the offline-sync stuff in Azure's mobile app services SDK.
I'm aware that there have been various changes recently in the SDK. I want to define client models according to the latest spec, but not sure which types to use.
These are the offline-sync metadata properties, typically seen in most examples/tutorials:
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
[Version]
public string Version { get; set; }
[CreatedAt]
public DateTimeOffset CreatedAt { get; set; }
[UpdatedAt]
public DateTimeOffset UpdatedAt { get; set; }
[Deleted]
public bool Deleted { get; set; }
But some documentation and examples, as well as various official (too many!) samples/quickstarts on GitHub, use a combination of types.
So I've seen this too in various places:
[JsonProperty(PropertyName = "id")]
public Guid Id { get; set; } // Guid is used here, not string
[Version]
[JsonProperty(PropertyName = "version")] // Needed? I assume the attribute is enough
public byte[] Version { get; set; } // byte[] is used here, not string
Under the covers everything is done via REST calls, and thus strings. So I assume the client SDK performs various type conversions.
But I don't want my app to bomb inexplicably at some point in the future, when things change. So which officially supported types should I be using?
The client SDK requires only a string Id field (that should be named "Id", unless you want to jump through a bunch of hoops). The value of the string can be any unique string. The Server SDKs use a string-converted GUID by default. When using offline sync, the client SDK also generates a string GUID unless an ID is specified. When using the online IMobileServiceTable APIs, the client lets the server generate the ID.
The rest of the fields are optional and should either have the types you listed, or be convertible to them.
Here's your data model, with comments on the various fields:
// required, should be called Id, *must* be of type string when using offline sync
// When not using offline sync, should be string-convertible.
// When using offline sync, the client SDK uses a new string-converted GUID for this, unless
// an ID is specified.
// When using offline sync, Ids are not mutable, so use something that can be client generated
public string Id { get; set; }
// optional. Using a Version field opts you into optimistic concurrency, where
// the server will reject updates that are done against an older version
// of an object. This means you need a conflict handler.
// To use a client-wins policy, remove this property from your client object
[Version]
public string Version { get; set; }
// optional. Cannot be set on the client, will be sent from the server
[CreatedAt]
public DateTimeOffset CreatedAt { get; set; }
// optional. Cannot be set on the client, will be sent from the server
[UpdatedAt]
public DateTimeOffset UpdatedAt { get; set; }
// should generally not be used in the client object at all. This field tracks
// which objects have been deleted so that they are automatically purged
// from the client's offline sync store
[Deleted]
public bool Deleted { get; set; }
Looks like you can use almost anything for the id column, as long as it's unique. Even an email address! (feels like NoSQL...) I've decided on a Guid, so all entities are consistent upon creation (no need to wait for server's response).
I've decided upon a byte array for the version column, as it seems to return exactly that from the server.
EDIT: This is quite wrong. See comment below and new accepted answer above.

Modifying model causes project not to build

I'm working with code that was started by someone other than me, so I'm not entirely familiar with the structure. However, I decided I needed to change one of the variables in one of the models. I needed to switch it from
[ForeignKey("JobFunctionDemandId")]
public virtual JobFunctionDemand JobFunctionDemand { get; set; }
public int JobFunctionDemandId { get; set; }
to
[ForeignKey("SpecificRequirementId")]
public virtual SpecificRequirement SpecificRequirement { get; set; }
public int SpecificRequirementId { get; set; }
I thought this would be a relatively small change. I realized, however, that these variables correspond to tables in a database, and so I switched all instances of JobFunctionDemand and JobFunctionDemandId to SpecificRequirement and SpecificRequirementId respectively. However, now when I try to run the Update-Database command in the package manager console, I get the error "The project 'ProjectName' failed to build."
I'm guessing the issue here is that I'm modifying the structure of an existing database, but I'm not really sure how to fix it.

Dealing with Object Graphs - Web API

I recently encountered a (hopefully) small issue when toying around with a Web API project that involves returning object graphs so that they can be read as JSON.
Example of Task Object (generated through EF) :
//A Task Object (Parent) can consist of many Activities (Child Objects)
public partial class Task
{
public Task()
{
this.Activities = new HashSet<Activity>();
}
public int TaskId { get; set; }
public string TaskSummary { get; set; }
public string TaskDetail { get; set; }
public virtual ICollection<Activity> Activities { get; set; }
}
within my ApiController, I am requested a specific Task (by Id) along with all of it's associated Activities, via:
Example of Single Task Request
//Simple example of pulling an object along with the associated activities.
return repository.Single(t => t.Id == id).Include("Activities");
Everything appears to be working fine - however when I attempt to navigate to a URL to access this, such as /api/tasks/1, the method executes as it should, but no object is returned (just a simple cannot find that page).
If I request an Task that contains no activities - everything works as expected and it returns the proper JSON object with Activities : [].
I'm sure there are many way to tackle this issue - I just thought I would get some insight as to what people consider the best method of handling this.
Considered Methods (so far):
Using an alternative JSON Parser (such as Newtonsoft.JSON) which fixed the issue but appended $id and $refs throughout the return data, which could make parsing for Knockout difficult I believe.
Using projection and leveraging anonymous types to return the data. (Untested so far)
Removing the Include entirely and simply accessing the Child Data through another request.
Any and all suggestions would be greatly appreciated.
I had a similar issue with EF types and Web API recently. Depending on how your generated EF models are setup, the navigation properties may result in circular dependencies. So if your generated Activity class has a Task reference the serializer will try to walk the object graph and get thrown in a little nasty cycle.
One solution would be to create a simple view model to get the serializer working
public class TaskViewModel {
public TaskViewModel ()
{
this.Activities = new List<ActivityViewModel>();
}
public int TaskId { get; set; }
public string TaskSummary { get; set; }
public string TaskDetail { get; set; }
public virtual IList<ActivityViewModel> Activities { get; set; }
}
public class ActivityViewModel{
public ActivityViewModel()
{
}
//Activity stuff goes here
//No reference to Tasks here!!
}
Depending on what you're doing, you may even be able to create a flatter model than this but removing the Task reference will help the serialization. That's probably why it worked when Activities was empty

Categories