Closed DLade closed 3 years ago
yeah HTTP POST/PUT/DELETE is on the roadmap (https://github.com/gost/sensorthings-net-sdk/blob/master/README.md#roadmap), at the time I created this only HTTP GET was needed.
What do you thing about that:
public async Task<Response<T>> Create<T>(T entity) where T : AbstractEntity {
if (entity == null) {
throw new ArgumentNullException(nameof(entity));
}
// workaround: creting the object the Id should be ignored at all
entity.Id = null;
return await Http.PostJson(GetEntityUrl(entity.GetType()), entity);
}
public async Task<Response<T>> Read<T>(T entity) where T : AbstractEntity {
if (entity == null) {
throw new ArgumentNullException(nameof(entity));
}
return await Get<T>(entity.GetType(), entity.Id, null);
}
public async Task<Response<T>> Update<T>(T entity) where T : AbstractEntity {
if (entity == null) {
throw new ArgumentNullException(nameof(entity));
}
return await Http.PatchJson(GetEntityUrl(entity.GetType()), entity);
}
public async Task<Response<T>> Delete<T>(T entity) where T : AbstractEntity {
if (entity == null) {
throw new ArgumentNullException(nameof(entity));
}
return await Http.DeleteJson<T>(GetEntityUrl(entity.GetType()));
}
private async Task<Response<T>> Get<T>(Type get, string id, OdataQuery odata) {
var url = GetEntityUrl(get, id);
url = odata != null ? odata.AppendOdataQueryToUrl(url) : url;
return await Http.GetJson<T>(url);
}
private async Task<Response<T>> Get<T>(Type get, Type by, string id, OdataQuery odata) {
if (by == null) {
throw new ArgumentNullException(nameof(by));
}
if (string.IsNullOrEmpty(id)) {
throw new ArgumentException("ID is required", nameof(id));
}
var url = $"{GetEntityUrl(by, id)}/{get.GetString(by)}";
url = odata != null ? odata.AppendOdataQueryToUrl(url) : url;
return await Http.GetJson<T>(url);
}
private string GetEntityUrl(Type type, string id = null) {
var idString = string.IsNullOrEmpty(id) ? "" : $"({id})";
return $"{_homedoc.GetUrlByEntityName(type.GetString())}{idString}";
}
}
It's rather simple using the new type-vs-enum pull request. I already implemented it but tested create(Thing) only, yet.
(I'm pretty sure you know CRUD - see https://en.wikipedia.org/wiki/Create,_read,_update_and_delete).
yes looks like a nice method to support HTTP POST/PUT/DELETE methods. Would be nice to have those methods in unit tests too. Current unit test coverage is 72.35%
Using a prerelease in my own project I found out, that the methods about can be written like that:
// TODO - return Id of new object (note: Response has the Header 'Location' by Spec)
public bool Create<T>(T entity)
where T : AbstractEntity, new() {
var response = ValidateAndGet(sensorThingsClient.Create(entity));
return response.Success;
}
public T Read<T>(string id)
where T : AbstractEntity, new() {
var response = ValidateAndGet(sensorThingsClient.Read(new T() { Id = id }));
return response.Result;
}
public bool Update<T>(T entity)
where T : AbstractEntity, new() {
var response = ValidateAndGet(sensorThingsClient.Update(entity));
return response.Success;
}
public bool Delete<T>(string id)
where T : AbstractEntity, new() {
var response = ValidateAndGet(sensorThingsClient.Delete(new T() { Id = id }));
return response.Success;
}
note: This is the code of my own facade class. I would implement the code for "our" service as well.
Moreover there is a problem using Create: The user would need the Id of the created entity in return. The HTTP response has the Header 'Location' by Spec - so we can use that but need to parse it from string (not optimal but possible).
I'm working on this solution ...
yes the location is the address of the just created resource. So it's a string not only an id.
We also have to think about what happens when something goes wrong when creating new items (for example server returns http 500).
You're right, I did not think about the error handling yet. Currently it just breaks the runtime if an exception is thrown.
If you wanna have some fun, the code is nearly ready (I use it in my own project like this): https://github.com/gost/sensorthings-net-sdk/pull/20
Missing tests for SensorThingsEntityHandler
and does not return the 'Id' with Create
yet.
But the still existing (29) tests and all of my own are running green.
I'm one the right way ... ;-)
It's done. You should have an Eye on the Pull-Request #20 :-)
The reason I need to write my own SensorThings Service is the lack of POST methods here.
Maybe I can combine my work with yours ...