Using DateTime object as DataMember? - wcf

I need to send in my web service some information about the time + date .
So i want to use the DateTime.
Can i define the DateTime as DataMember ?
I try to define it as as datamember - but i got an exception ( catastrophic failure )

Create new WCFDate class, and this class outputs a string in a set format, this allows it to be easily read by what ever needs to. Then replace all of Ur DateTimes with WCFDate.
public class WCFDate
{
public static string DateTimeFormat = "yyyy-MM-dd hh:mm:ss zz";
public string Data { get; set; }
public WCFDate() { }
public WCFDate(string data)
{
Data = data;
}
public WCFDate(DateTime date)
{
Data = date.ToString(DateTimeFormat);
}
public WCFDate(DateTime? date)
{
if (date.HasValue)
{
Data = date.Value.ToString(DateTimeFormat);
}
}
public bool HasDate
{
get
{
return !string.IsNullOrWhiteSpace(Data);
}
}
public DateTime GetDate()
{
try
{
return DateTime.ParseExact(Data, DateTimeFormat, CultureInfo.CurrentCulture);
}
catch
{
return new DateTime();
}
}

Related

I Cant Return List Type from Wcf

[DataContract]
public class UserDetails
{
string _userid;
string tckimlik;
string ad;
string tarih;
string aciklama;
[DataMember]
public string userid
{
get { return _userid; }
set { _userid = value; }
}
[DataMember]
public string Tckimlik
{
get { return tckimlik; }
set { tckimlik = value; }
}
[DataMember]
public string Ad
{
get { return ad; }
set { ad = value; }
}
[DataMember]
public string Tarih
{
get { return tarih; }
set { tarih = value; }
}
[DataMember]
public string Aciklama
{
get { return aciklama; }
set { aciklama = value; }
}
}
public interface IService1
{
[OperationContract]
List<UserDetails> GetAllPersons();
}
My Class DataContract and OperationContract given above.
My Method GetAllPersons type of List beloew.
public List<UserDetails> GetAllPersons()
{
List<UserDetails> userL = new List<UserDetails>();
try
{
NpgsqlConnection con = new NpgsqlConnection("");
con.Open();
NpgsqlCommand cmd = new NpgsqlCommand("SELECT * FROM RegistrationTable",con);
NpgsqlDataAdapter sda = new NpgsqlDataAdapter(cmd);
NpgsqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
UserDetails us = new UserDetails()
{
userid = reader[0].ToString(),
Tckimlik = reader[1].ToString(),
Ad = reader[2].ToString(),
Tarih = reader[3].ToString(),
Aciklama = reader[4].ToString()
};
userL.Add(us);
}
con.Close();
return userL;
}
catch (Exception)
{
throw;
}
}
The Code above is in WCF Service. I want to call GetAllPersons method in Xamarin. But i have trouble with it. My Xamarin code is below.
void getVisitor()
{
List<ServiceReference1.UserDetails> getir = new List<ServiceReference1.UserDetails>();
getir = service.GetAllPersonsAsync();
}
When i wanted to call method in service, i get an error given below.
Severity Code Description Project File Line Suppression State
Error CS0029 Cannot implicitly convert type 'System.Threading.Tasks.Task<ServiceReference1.GetAllPersonsResponse>' to 'System.Collections.Generic.List<ServiceReference1.UserDetails>' XamarinCRUD C:\Users\Eyyub\source\repos\XamarinCRUD\XamarinCRUD\XamarinCRUD\MainPage.xaml.cs 59 Active
Who can hint me, appreciate it!
Best for all!
I also checked logs and no show. Some says that WCF doesnt (de)serialize List return type. Is it true? if yes, what is the solution?. When i used same service through FormApp, works fine. But Xamarin doesnt..

.NET CORE WEB API accept list of integers as an input param in HTTP GET API

I am using .net core 3+ web api.
Below is how my action looks like below, it uses HTTP GET and I want to pass few fields and one of the fields is a list of integers.
[HttpGet]
[Route("cities")]
public ActionResult<IEnumerable<City>> GetCities([FromQuery] CityQuery query)
{...}
and here is CityQuery class -
public class CityQuery
{
[FromQuery(Name = "stateids")]
[Required(ErrorMessage = "stateid is missing")]
public string StateIdsStr { get; set; }
public IEnumerable<int> StateList
{
get
{
if (!string.IsNullOrEmpty(StateIdsStr))
{
var output = StateIdsStr.Split(',').Select(id =>
{
int.TryParse(id, out var stateId);
return stateId;
}).ToList();
return output;
}
return new List<int>();
}
}
}
Is there a generic way I can use to accept list of integers as input and not accept string and then parse it?
Or is there a better way to do this? I tried googling but could not find much. Thanks in advance.
This can help
[HttpGet]
[Route("cities")]
public ActionResult<IEnumerable<City>> GetCities([FromQuery] int[] stateids)
{
...
}
but the query string will change to
https://localhost/api/controller/cities?stateids=1&stateids=2&stateids=3
If you required comma separated query string with integer, you can go for Custom model binder
https://learn.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding?view=aspnetcore-3.1
You can use custom model binding, below is a working demo:
Model:
public class CityQuery
{
public List<int> StateList{ get; set; }
}
CustomModelBinder:
public class CustomModelBinder: IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var values = bindingContext.ValueProvider.GetValue("stateids");
if (values.Length == 0)
{
return Task.CompletedTask;
}
var splitData = values.FirstValue.Split(',');
var result = new CityQuery()
{
StateList = new List<int>()
};
foreach(var id in splitData)
{
result.StateList.Add(int.Parse(id));
}
bindingContext.Result = ModelBindingResult.Success(result);
return Task.CompletedTask;
}
}
Applying ModelBinding Attribute on Action method:
[HttpGet]
[Route("cities")]
public ActionResult GetCities([ModelBinder(BinderType = typeof(CustomModelBinder))] CityQuery query)
{
return View();
}
when the url like /cities?stateids=1,2,3, the stateids will be filled to StateList
I think you just need to use [FromUri] before int array parameter :
public ActionResult<IEnumerable<City>> GetCities([FromUri] int[] stateList)
And request would be like :
/cities?stateList=1&stateList=2&stateList=3

How to send object which contains IEnumerable via Refit on NetCore?

I have to send a request object via Refit which contains 2 IEnumerable and one string, but for some reason I can't send the object forward.
I've tried to use all the paramets from the interface. Ex: [Query(CollectionFormat.Csv)] or Multi / Pipes but no success.
I've also tried to create my own CustomUrlParameterFormatter but unfortunately here I'm stuck, because I don't see a good way to retrieve the name of the property from the object request that I'm sending.
The code for CustomUrlParameterFormatter
public class CustomUrlParameterFormatter : IUrlParameterFormatter
{
public string Format(object value, ParameterInfo parameterInfo)
{
if(value is IEnumerable enumerable)
{
var result = ToQueryString(enumerable, parameterInfo.Name);
return result;
}
return string.Empty;
}
public static string ToQueryString(IEnumerable query, string parameterName)
{
var values = query.Cast<object>().Select(ToString).ToArray();
var separator = parameterName + "=";
return values.Any() ? separator + string.Join("&" + separator, values) : "";
}
public static string ToString(object value)
{
var json = JsonConvert.SerializeObject(value).Replace("\\\"", "\"").Trim('"');
return Uri.EscapeUriString(json);
}
}
The Call from the IService that I'm using
[Get("/TestMethod")]
Task<HttpResponseMessage> TestMethod([Query]TestRequestDTO requestDTO, [Header("X-Correlation-ID")] string correlationId);
The Request object
public class TestRequestDTO
{
public IEnumerable<long> EnumOne { get; set; }
public IEnumerable<long> EnumTwo { get; set; }
public string MethodString { get; set; }
}
Also the RefitClient configuration
var refitSettings = new RefitSettings();
refitSettings.UrlParameterFormatter = new CustomUrlParameterFormatter();
services.AddRefitClient<IService>(refitSettings)
.ConfigureHttpClient(c => c.BaseAddress = new Uri(settings.Services.IService));
What I'm trying to achieve is something like
TestMethod?EnumOne =123&EnumOne =321&EnumTwo=123&EnumTwo=321&methodString=asdsaa
and instead I'm receiving other behavior
without CustomUrlParameterFormatter()
TestMethod?EnumOne=System.Collections.Generic.List`1%5BSystem.Int64%5D&EnumTwo=System.Collections.Generic.List`1%5BSystem.Int64%5D&MethodString=sdf

Xamarin SQLite database creating for all tables

I have working on this topic for 4 hours but I couldn't get any solution.
My problem is actually;
I have 5 table and I wanna create one controller to create different tables.
My current codes are below but this codes create only one table.
public interface ISQLite
{
SQLiteConnection GetConnection();
}
-
public class TodoItem
{
public TodoItem ()
{
}
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string Name { get; set; }
public string Notes { get; set; }
public bool Done { get; set; }
}
-
public class TodoItemDatabase
{
static object locker = new object ();
SQLiteConnection database;
/// <summary>
/// Initializes a new instance of the <see cref="Tasky.DL.TaskDatabase"/> TaskDatabase.
/// if the database doesn't exist, it will create the database and all the tables.
/// </summary>
/// <param name='path'>
/// Path.
/// </param>
public TodoItemDatabase()
{
database = DependencyService.Get<ISQLite> ().GetConnection ();
// create the tables
database.CreateTable<TodoItem>();
}
public IEnumerable<TodoItem> GetItems ()
{
lock (locker) {
return (from i in database.Table<TodoItem>() select i).ToList();
}
}
public IEnumerable<TodoItem> GetItemsNotDone ()
{
lock (locker) {
return database.Query<TodoItem>("SELECT * FROM [TodoItem] WHERE [Done] = 0");
}
}
public TodoItem GetItem (int id)
{
lock (locker) {
return database.Table<TodoItem>().FirstOrDefault(x => x.ID == id);
}
}
public int SaveItem (TodoItem item)
{
lock (locker) {
if (item.ID != 0) {
database.Update(item);
return item.ID;
} else {
return database.Insert(item);
}
}
}
public int DeleteItem(int id)
{
lock (locker) {
return database.Delete<TodoItem>(id);
}
}
}
-
public class SQLite_Android : ISQLite
{
public SQLite_Android()
{
}
#region ISQLite implementation
public SQLite.SQLiteConnection GetConnection()
{
var sqliteFilename = "TodoSQLite.db3";
string documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal); // Documents folder
var path = Path.Combine(documentsPath, sqliteFilename);
// This is where we copy in the prepopulated database
Console.WriteLine(path);
if (!File.Exists(path))
{
var s = Forms.Context.Resources.OpenRawResource(Resource.Raw.TodoSQLite); // RESOURCE NAME ###
// create a write stream
FileStream writeStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
// write to the stream
ReadWriteStream(s, writeStream);
}
var conn = new SQLite.SQLiteConnection(path);
// Return the database connection
return conn;
}
#endregion
/// <summary>
/// helper method to get the database out of /raw/ and into the user filesystem
/// </summary>
void ReadWriteStream(Stream readStream, Stream writeStream)
{
int Length = 256;
Byte[] buffer = new Byte[Length];
int bytesRead = readStream.Read(buffer, 0, Length);
// write the required bytes
while (bytesRead > 0)
{
writeStream.Write(buffer, 0, bytesRead);
bytesRead = readStream.Read(buffer, 0, Length);
}
readStream.Close();
writeStream.Close();
}
}
--- How can I create multi tables in one controller ?
Looks like you are using Sqlite.net-pcl, right?
Multiple tables from the same model are not supported (it's for simple cases only).
You can create multiple models (possibly by just inheriting) and then call CreatTable<T> for each of them.
I solved problem. Maybe this solution helps somenone.
I have two DbHepler Class and two model class for creating two tables on DB.
Base connection codes are same;
public interface ISQLite
{
SQLiteConnection GetConnection();
}
This is the App.cs file;
public class App : Application {
public App()
{
authenticationDB = new AuthenticationDbHelper(Database);
settingsDbHelper = new SettingsDbHelper(Database);
MainPage = new Views.MainMenuPage();
}
public static CreateDB Database
{
get
{
if (database == null)
{
database = new CreateDB();
}
return database;
}
}
}
The CreateDB class is necessary for create one db for all tables
public class CreateDB
{
public SQLiteConnection database;
public object locker = new object();
public CreateDB()
{
database = DependencyService.Get<ISQLite>().GetConnection();
}
}
This interface is necessary for created tables actions. Since implement this class we can use theese methods all tables.(T is table class)(To understand look AuthenticationDBHelper class)
public interface SQLiteBase<T>
{
IEnumerable<T> GetItems();
T GetItem(long id);
long SaveItem(T item);
void UpdateItem(T item);
int DeleteItem(int id);
int Clear();
int getCount();
}
This DbHelper class will be used for delete,insert,clear.... items.
public class AuthenticationDbHelper : SQLiteBase<AuthenticationDbTable>
{
SQLiteConnection database;
object locker;
public AuthenticationDbHelper(CreateDB db)
{
database = db.database;
locker = db.locker;
database.CreateTable<AuthenticationDbTable>();
}
public int Clear()
{
lock(locker)
{
return database.DeleteAll<AuthenticationDbTable>();
}
}
public int DeleteItem(int id)
{
lock (locker)
{
return database.Delete<AuthenticationDbTable>(id);
}
}
public AuthenticationDbTable GetItem(long id)
{
lock (locker)
{
return database.Table<AuthenticationDbTable>().FirstOrDefault(x => x.UserId == id);
}
}
public IEnumerable<AuthenticationDbTable> GetItems()
{
lock (locker)
{
return (from i in database.Table<AuthenticationDbTable>() select i).ToList();
}
}
public long SaveItem(AuthenticationDbTable item)
{
lock (locker)
{
return database.Insert(item);
}
}
public void UpdateItem(AuthenticationDbTable item)
{
lock(locker)
{
database.Update(item);
}
}
public int getCount()
{
return GetItems().Count();
}
}
I know it is very confused but this is the last. We will create model for authentication.
public class AuthenticationDbTable
{
public AuthenticationDbTable(long userId, string sessionId, string username, string clientuuid)
{
this.userId = userId;
this.sessionId = sessionId;
this.username = username;
this.clientuuid = clientuuid;
}
private long userId;
private string sessionId;
private string username;
private string clientuuid;
[PrimaryKey]
public long UserId
{
get { return userId; }
set { userId = value; }
}
public string SessionId
{
get { return sessionId; }
set { sessionId = value; }
}
public string Username
{
get { return username; }
set { username = value; }
}
public string Clientuuid
{
get { return clientuuid; }
set { clientuuid = value; }
}
}
Using
AuthenticationDbTable authentication = new AuthenticationDbTable(authenticateduser.User.UserId, r.Retval.SessionStatus.SessionId, authenticateduser.User.Name, authenticateduser.Clientuuid);
App.authenticationDB.SaveItem(authentiaction);
Note
For creating second table you can use same way. You should create second DbHelper and model class. Assume that you will create a table for settings. You should create SettingsDbHelper and SettingsDbTable class. through same way.
Thank you :)

How to get WebAPI XML serializer to use TypeConverter

In a ASP.NET Web API project, I've got a custom type with a TypeConverter that handles the to and from for string conversions, as described here:
http://blogs.msdn.com/b/jmstall/archive/2012/04/20/how-to-bind-to-custom-objects-in-action-signatures-in-mvc-webapi.aspx
The custom type is used as a property in my model and this works great. The json for my model object includes my custom object as the string value created from my TypeConverter.
So then I switch the request to accept XML instead and the TypeConverter is no longer invoked and my object is incorrectly serialized.
How to I get the XML serializer to utilize the TypeConverter as the JSON one does. The article referenced made it sound like the use of TypeConverters, when present, was a predictable feature. If it is completely at the whim of the serializer then making APIs that express data in both XML and JSON in a consistent way is nearly impossible.
Sample code from the article, plus a bit of context:
[TypeConverter(typeof(LocationTypeConverter))]
public class Location
{
public int X { get; set; }
public int Y { get; set; }
// Parse a string into a Location object. "1,2" --> Loc(X=1,Y=2)
public static Location TryParse(string input)
{
var parts = input.Split(',');
if (parts.Length != 2)
{
return null;
}
int x,y;
if (int.TryParse(parts[0], out x) && int.TryParse(parts[1], out y))
{
return new Location { X = x, Y = y };
}
return null;
}
public override string ToString()
{
return string.Format("{0},{1}", X, Y);
}
}
public class LocationTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value)
{
if (value is string)
{
return Location.TryParse((string) value);
}
return base.ConvertFrom(context, culture, value);
}
}
Create a model with that class:
public class SampleModel
{
public int One { get; set;}
public string Two { get; set;}
public Location Three { get; set;}
}
Create a ApiController with a method like this:
public SampleModel Get()
{
return new SapleModel { One = 1, Two = "Two", Three = new Location { X = 111, Y = 222 } };
}
That's it. Using fiddler and try them both and note that Location serializes using the converter into the single-line comma-seperated format like this (Three="111,222") with Json but not with XML.