Trying to get the server timestamp at the CreatedAt document field before the document is added to the cloud. So it could be applied to the Time property and also saved locally, However this is what I get:
My ChatTestMessageGroup Model
public class ChatTestMessageGroup : TimeTest
{
public long MessageId { get; set; }
public string Message { get; set; }
public string Time { get; set; }
}
public class TimeTest
{
[ServerTimestamp]
public Timestamp CreatedAt { get; set; }
public Timestamp StampAt { get; set; }
}
Send Message Execution code
private async Task SendTestMessageAsync()
{
if (string.IsNullOrWhiteSpace(Message)) return;
// under testing.
var test = new ChatTestMessageGroup()
{
MessageId = new Timestamp().ToDateTime().Ticks,
Message = Message.Trim(),
};
test.Time = $"{test.CreatedAt.ToDateTime():HH:mm}";
await CloudService.CS.SendMessageAsync(test);
Message = "";
}
Write To Cloud Code
public async Task SendMessageAsync(ChatTestMessageGroup testMessage)
{
IDocumentReference doc = CrossCloudFirestore.Current.Instance.Collection("Testing").Document(DateTime.Now.Day.ToString());
await doc.Collection("Tester").Document(${testMessage.CreatedAt.Seconds}").SetAsync(testMessage);
}
The plugin I'm using
Plugin.CloudFirestore
Trying to get the server timestamp at the CreatedAt document field before the document is added to the cloud.
This is not possible. The time is taken at the server the moment the document is created. The client app can't be certain what the time is on the server because its own clock could be wrong. You can only get the timestamp that was written by reading the document back.
Related
I was writing a code for exchange app using my local bank api.
JSON response looks like this:
{"date":"01.12.2014",
"bank":"PB",
"baseCurrency":980,
"baseCurrencyLit":"UAH",
"exchangeRate[{"baseCurrency":"UAH","currency":"AUD","saleRateNB":12.8319250,"purchaseRateNB":12.8319250,{"baseCurrency":"UAH","currency":"CAD","saleRateNB":13.2107400,"purchaseRateNB":13.2107400,"saleRate":15.0000000,"purchaseRate":13.0000000},
*other currencies here in exchangeRate array*}]
I am using this approach
private static async Task ProcessExchangeRate()
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var responce = await client.GetAsync("https://api.privatbank.ua/p24api/exchange_rates?json&date=01.12.2020");
if (responce.IsSuccessStatusCode)
{
ExchangeRate rate = await responce.Content.ReadAsAsync<ExchangeRate>();
}
}
ExchangeRate class
[JsonPropertyName("date")]
public string Date { get; set; }
[JsonPropertyName("exchangeRate")]
public string Rates { get; set; }
For some reason it works for Date property, but not for Rates. What should I do?
I found out, that I should have use
public object[] exchangeRate { get; set; }
for exchangeRate, thx #Kerem for pointing me on it.
I am building a simple to-do list api using ASP.Net Core. It has two main two main models, a List model and a Task model. Each List has many Tasks. I build the models like this:
List Model:
namespace ToDoList.Models
{
public class List
{
[Key]
public int ListId { get; set; }
[Required]
[StringLength(25)]
public string Title { get; set; }
public string Colour { get; set; }
public virtual ICollection<Task> Tasks { get; set; }
public List()
{
Tasks = new List<Task>();
Colour = "secondary";
}
}
}
Task Model:
namespace ToDoList.Models
{
public class Task
{
[Key]
public int TaskId { get; set; }
[Required]
[StringLength(50)]
public string Title { get; set; }
public bool Done { get; set; }
public int ListId { get; set; }
public virtual List List { get; set; }
public Task()
{
Done = false;
}
}
}
When I send a post request to create a new task I am struggling to get the created task to be added to the Icollection part of the List model.
My Controller looks like this:
// POST: api/Tasks
[HttpPost]
public async Task<ActionResult<Models.Task>> PostTask(Models.Task task)
{
_context.Tasks.Add(task);
await _context.SaveChangesAsync();
return CreatedAtAction("GetTask", new { id = task.TaskId }, task);
}
If I send this data as JSON as a POST request:
{ title: "A New Task", listId: 11 }
I create this Task:
{"taskId":16,"title":"A New Task","done":false,"listId":11,"list":null}
As you can see it has the right listId but the list attached is null.
Also the task does not get added to the list.Tasks collection.
{"listId":11,"title":"Learn ASP.Net Core","colour":"secondary","tasks":[]}
As you can see tasks is still empty.
How do I get it set up that when ever a task is created it is always add to List.Tasks and then Tasks.List has the correct list attached to it, not null.
Also On my SQL Sever Database I expected to see a Tasks in the Lists table but I don't. Can anyone explain why?
SQL Sever Database Columns Picture
You could load the List entity from your DbContext and add it to the Task object you are returning:
[HttpPost]
public async Task<ActionResult<Models.Task>> PostTask(Models.Task task)
{
_context.Tasks.Add(task);
await _context.SaveChangesAsync();
task.List = _context.Lists.Single(task.ListId);
return CreatedAtAction("GetTask", new { id = task.TaskId }, task);
}
or you could return an instance of the Task loaded from the DbContext with included List:
var taskFromDb = _context.Tasks.Include(x => x.List).Single(x => x.Id = task.Id);
return CreatedAtAction("GetTask", new { id = task.TaskId }, taskFromDb);
To get a list with tasks, it needs to be loaded from the DbContext:
var listWithTasks = _context.Lists.Include(x => x.Tasks).Single(x => x.Id == task.ListId);
The problem that I'm having is I can't get the query to check to see if the same text already exists in the same attribute within the database.
Below is the part of the controller. This query contains if statement.
[AllowAnonymous]
[HttpPost]
public async Task<IActionResult> PostBook(Booking bookings, string Title)
{
if(!ModelState.IsValid)
{
var SearchData = await _context.bookings.Where(x => x.Title == Title).SingleOrDefaultAsync();
if (SearchData != null)
return BadRequest("bad request");
}
_context.bookings.Add(bookings);
_context.SaveChanges();
return Ok();
}
Whenever I input the same data it comes out as either 200 requests or 500 internal error. The expected outcome should be a 400 bad request. When I make a Post request from postman 400 bad request should appear. This is similar to checking if a username already exists. What I'm trying to implement is a restaurant reservation system that won't allow users to have the same name or time? How can you do this for Time with hourly based sessions and string?
I'm wondering if any of you guys have done this before checking if the same value or text exists within the database.
I'm using .net core with vs code and Postman to post the JSON data.
below is my model for the booking model.
public class Booking
{
public int Id { get; set; }
public string Title { get; set; }
public DateTime Date { get; set; }
public string Request { get; set; }
public int NoPeople { get; set; }
public Customer Customer { get; set;}
}
Issue is that value used to check for uniqueness is different than value saved to the database.
Remove Title parameter and use title property from booking instance to check for uniqueness.
[AllowAnonymous]
[HttpPost]
public async Task<IActionResult> PostBook(Booking newBooking)
{
var titleExists =
await _context.bookings.AnyAsync(b => b.Title == newBooking.Title);
if (titleExists)
return BadRequest($"Title '{newBooking.Title}' already exists");
}
_context.bookings.Add(newBooking);
await _context.SaveChangesAsync();
return Ok();
}
With AnyAsync function you can check for existence without loading whole record in case such record exists.
I'm new to the ASP.Net Web API. I'm trying to interact with the Recurly REST based API and I am getting errors like below during my ReadAsAsync call which is the point I believe it attempts to serialize the response.
{"Error in line 1 position 73. Expecting element 'account' from namespace 'http://schemas.datacontract.org/2004/07/RecurlyWebApi.Recurly'.. Encountered 'Element' with name 'account', namespace ''. "}
Here is my HttpClient implementation, simplified for brevity:
public class RecurlyClient
{
readonly HttpClient client = new HttpClient();
public RecurlyClient()
{
var config = (RecurlySection)ConfigurationManager.GetSection("recurly");
client.BaseAddress = new Uri(string.Format("https://{0}.recurly.com/v2/", config.Subdomain));
// Add the authentication header
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(config.ApiKey)));
// Add an Accept header for XML format.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
}
public T Get<T>(string id)
{
var accounts = default(T);
// Make the request and get the response from the service
HttpResponseMessage response = client.GetAsync(string.Concat("accounts/", id)).Result; // Blocking call!
if (response.IsSuccessStatusCode)
{
// Parse the response body. Blocking!
accounts = response.Content.ReadAsAsync<T>().Result;
}
return accounts;
}
}
And here is my model:
[XmlRoot("account")]
public class Account
{
[XmlAttribute("href")]
public string Href { get; set; }
[XmlElement("account_code")]
public string AccountCode { get; set; }
[XmlElement("state")]
public AccountState State { get; set; }
[XmlElement("username")]
public string Username { get; set; }
[XmlElement("email")]
public string Email { get; set; }
[XmlElement("first_name")]
public string FirstName { get; set; }
[XmlElement("last_name")]
public string LastName { get; set; }
[XmlElement("company_name")]
public string Company { get; set; }
[XmlElement("accept_language")]
public string LanguageCode { get; set; }
[XmlElement("hosted_login_token")]
public string HostedLoginToken { get; set; }
[XmlElement("created_at")]
public DateTime CreatedDate { get; set; }
[XmlElement("address")]
public Address Address { get; set; }
}
And an example of the XML response from the service:
<account href="https://mysubdomain.recurly.com/v2/accounts/SDTEST01">
<adjustments href="https://mysubdomain.recurly.com/v2/accounts/SDTEST01/adjustments"/>
<invoices href="https://mysubdomain.recurly.com/v2/accounts/SDTEST01/invoices"/>
<subscriptions href="https://mysubdomain.recurly.com/v2/accounts/SDTEST01/subscriptions"/>
<transactions href="https://mysubdomain.recurly.com/v2/accounts/SDTEST01/transactions"/>
<account_code>SDTEST01</account_code>
<state>active</state>
<username>myusername</username>
<email>simon#example.co.uk</email>
<first_name>First name</first_name>
<last_name>Last name</last_name>
<company_name>My Company Name</company_name>
<vat_number nil="nil"></vat_number>
<address>
<address1>My Address Line 1/address1>
<address2>My Address Line 2</address2>
<city>My City</city>
<state>My State</state>
<zip>PL7 1AB</zip>
<country>GB</country>
<phone>0123456789</phone>
</address>
<accept_language nil="nil"></accept_language>
<hosted_login_token>***</hosted_login_token>
<created_at type="datetime">2013-08-22T15:58:17Z</created_at>
</account>
I think the problem is because by default the DataContractSerializer is being used to deserialize the XML, and by default the DataContractSerializer uses a namespace of namespace http://schemas.datacontract.org/2004/07/Clr.Namespace. (In this case Clr.Namepace is RecurlyWebApi.Recurly.)
Because your XML has attributes, you need to use the XmlSerializer instead of the DataContractSerializer, and you're set up to do this because your account class is decorated with Xml* attributes. However, you have to use an XmlMediaTypeFormatter which is using the XmlSerializer. You can do this by setting a flag on the global XMLFormatter as described on this page:
var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
xml.UseXmlSerializer = true;
or by supplying a MediaTypeFormatter as a parameter to your ReadAsAsync call:
var xmlFormatter = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
xmlFormatter.UseXmlSerializer = true;
accounts = response.ReadAsAsync<T>(xmlFormatter).Result
Not 100% sure of this because this doesn't explain why the first 'account' in your error message is lower case - the DataContractSerializer should ignore the XmlRoot attribute.
Im fairly new to ASP.NET MCV 4 as well as Mongo DB and trying to build web API.
I thought I had finally got it right but when I start the app and enter: http://localhost:50491/api/document into my browser I get this error message
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.
Here is my code
This is the Document Class
public class Document
{
[BsonId]
public ObjectId DocumentID { get; set; }
public IList<string> allDocs { get; set; }
}
This is where the Connection to the DB is made:
public class MongoConnectionHelper
{
public MongoCollection<BsonDocument> collection { get; private set; }
public MongoConnectionHelper()
{
string connectionString = "mongodb://127.0.0.1";
var server = MongoServer.Create(connectionString);
if (server.State == MongoServerState.Disconnected)
{
server.Connect();
}
var conn = server.GetDatabase("cord");
collection = conn.GetCollection("Mappings");
}
Here is the ApiController Class:
public class DocumentController : ApiController
{
public readonly MongoConnectionHelper docs;
public DocumentController()
{
docs = new MongoConnectionHelper();
}
public IList<BsonDocument> getAllDocs()
{
var alldocs = (docs.collection.FindAll().ToList());
return alldocs;
}
}
I read futher on and the error message suggested:
Type 'MongoDB.Bson.BsonObjectId' with data contract name 'BsonObjectId:http://schemas.datacontract.org/2004/07/MongoDB.Bson' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
That is all good and well but how do I do that?
Either a) don't serialize your document classes over Web API, and create some DTOs meant to be serialized, or b) use something else as ID.
If you want an easy auto-generated ID, and you're OK with the fact that it will consume slightly more space, you can resort to the following "hack":
public class Document
{
public Document()
{
Id = ObjectId.GenerateNewId().ToString();
}
public string Id { get; set; }
}
This way, you'll get MongoIDs, but they'll be stored as a string.
If you need Web API2 responce in XML format , you need to handle the default Id like below
eg: ObjectId("507f191e810c19729de860ea")
Either you need to remove the Id from serialization.
[DataContract]
public class Document
{
[BsonId]
public string Id { get; set; }
[DataMember]
public string Title { get; set; } //other properties you use
}
Or You can change the Type of ID with custom logic
public class GuidIdGenerator : IIdGenerator
{
public object GenerateId(object container, object document)
{
return Guid.NewGuid();
}
public bool IsEmpty(object id)
{
return string.IsNullOrEmpty(id.ToString());
}
}
public class Document
{
[BsonId(IdGenerator = typeof(GuidIdGenerator))]
public string Id { get; set; }
public string Title { get; set; } //other properties you use
}