How to retrieve the serialized field name of an Elasticsearch Nest.Field - elasticsearch

I want to get the field name of a field which is created with Infer.Field<MyDocument>(doc => doc.StringField1).
Example code:
using System;
using Nest;
using Xunit;
namespace Elasticsearch.Tests
{
public class MyDocument
{
public string StringField1 { get; set; }
}
public class SerializeField
{
[Fact]
public void TestFieldName()
{
var connectionSettings = new ConnectionSettings(new Uri("http://myesdomain.com:9200"));
var client = new ElasticClient(connectionSettings);
var stringField = Infer.Field<MyDocument>(doc => doc.StringField1);
// TODO: Code to get then name of stringField when serialized
}
}
}
Can I leaverage the client in order to serialize the name of the stringField as it would do in any request?

Fortunately I found the answer myself:
Short:
client.SourceSerializer.Serialize(stringField, ms);
Complete:
using System;
using System.IO;
using System.Text;
using Nest;
using Xunit;
namespace Elasticsearch.Tests
{
public class MyDocument
{
public string StringField1 { get; set; }
}
public class SerializeField
{
[Fact]
public void TestFieldName()
{
var connectionSettings = new ConnectionSettings(new Uri("http://myesdomain.com:9200"));
var client = new ElasticClient(connectionSettings);
var stringField = Infer.Field<MyDocument>(doc => doc.StringField1);
string fieldName;
using (var ms = new MemoryStream())
{
client.SourceSerializer.Serialize(stringField, ms);
ms.Position = 0;
using (var reader = new StreamReader(ms, Encoding.UTF8))
{
fieldName = reader.ReadToEnd();
}
}
Assert.Equal("\"stringField1\"", fieldName);
}
}
}

There is a better solution that uses a Nest.FieldResolver.
using System;
using Nest;
using Xunit;
namespace Elasticsearch.Tests
{
public class MyDocument
{
public string StringField1 { get; set; }
}
public class TestClass
{
[Fact]
public void TestFieldName()
{
var connectionSettings = new ConnectionSettings(new Uri("http://myesdomain.com:9200"));
var fieldResolver = new FieldResolver(connectionSettings);
var stringField = Infer.Field<MyDocument>(doc => doc.StringField1);
var fieldName = fieldResolver.Resolve(stringField);
Assert.Equal("stringField1", fieldName);
}
}
}

Related

how to test IQueryable of strongly typed using xUnit in .NET CORE

I am working on a test project for .NET CORE Web API project. I have SchoolService class that implements numbers of methods as some of them below
Service Class
public class SchoolService : ISchoolService
{
private readonly ISchoolEntity schoolEntity;
public SchoolService(ISchoolEntity schoolEntity)
{
this.schoolEntity = schoolEntity;
}
public IQueryable<SchoolDataView> GetAllSchools()
{
var query = this.schoolEntity.GetAllSchool();
return query;
}
public SchoolDataView GetSchoolById(Guid Id)
{
var query = this.schoolEntity.GetSchoolById(Id);
return query;
}
I want to test
1- GetAllSchools return object type is of IQueryable?
2- How I use autofix or by another way for schoolEntity.GetAllSchool() return fake IQueryable?
Service Test
public class SchoolServiceTests
{
private readonly ISchoolService schoolService;
private readonly ISchoolEntity schoolEntity = Substitute.For<ISchoolEntity>();
public SchoolServiceTests()
{
schoolService = new SchoolService(schoolEntity);
}
[Fact]
public void GetAllSchool_ShouldReturn_IQueryableOfSchoolDataView()
{
//Arrange
//Act
var a = schoolEntity.GetAllSchool();
//Assert
Assert.??
}
}
I have written following test to achieve behaviour that I have stated in my question. Open to hearing more feedback and suggestions on it. Thanks
[Fact]
public void GetAllSchool_ShouldReturn_IQueryableOfSchoolDataView()
{
//Arrange
var schoolDataViewList = new List<SchoolDataView>
{
new SchoolDataView { SchoolID = Guid.NewGuid(), Name = "London Primary School"},
new SchoolDataView { SchoolID = Guid.NewGuid(), Name = "Windsor Gramer School"},
new SchoolDataView { SchoolID = Guid.NewGuid(), Name = "Kings College"},
new SchoolDataView { SchoolID = Guid.NewGuid(), Name = "Reading School"}
}.AsQueryable();
schoolEntity.GetAllSchool().Returns(schoolDataViewList);
//Act
var actualSchoolList = sut.GetAllSchools();
//Assert
Assert.IsAssignableFrom<IQueryable<SchoolDataView>>(actualSchoolList);
}
OR Using AutoFixture
[Fact]
public void GetAllSchool_ShouldReturn_IQueryableOfSchoolDataView()
{
//Arrange
var fixture = new Fixture();
var schoolDataViewMock = fixture.CreateMany<SchoolDataView>();
schoolEntity.GetAllSchool().Returns(schoolDataViewMock.AsQueryable());
//Act
var actualSchoolDataList = sut.GetAllSchools();
//Assert
Assert.IsAssignableFrom<IQueryable<SchoolDataView>>(actualSchoolDataList);
}

Xamarin MVVM passing data to other view

I want to pass the data to another view page. So far I can get the data I need to pass. My problem is how do I pass the data in MVVM. I used Application.Current.MainPage.Navigation.PushAsync(new DatabaseSyncPage(), true); When I add contactId inside DatabaseSyncPage() an error occurs. "The error is 'DatabaseSyncPage' does not contain a constructor that takes 1 arguments"
My code:
LoginPageViewModel.cs
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Input;
using TBSMobileApplication.Data;
using TBSMobileApplication.View;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace TBSMobileApplication.ViewModel
{
public class LoginPageViewModel : INotifyPropertyChanged
{
void OnProperyChanged(string PropertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
public string username;
public string password;
public string Username
{
get { return username; }
set
{
username = value;
OnProperyChanged(nameof(Username));
}
}
public string Password
{
get { return password; }
set
{
password = value;
OnProperyChanged(nameof(Password));
}
}
public class LoggedInUser
{
public string ContactID { get; set; }
}
public ICommand LoginCommand { get; set; }
public LoginPageViewModel()
{
LoginCommand = new Command(OnLogin);
}
public void OnLogin()
{
if (string.IsNullOrEmpty(Username) || string.IsNullOrEmpty(Password))
{
MessagingCenter.Send(this, "Login Alert", Username);
}
else
{
var current = Connectivity.NetworkAccess;
if (current == NetworkAccess.Internet)
{
var link = "http://192.168.1.25:7777/TBS/test.php?User=" + Username + "&Password=" + Password;
var request = HttpWebRequest.Create(string.Format(#link));
request.ContentType = "application/json";
request.Method = "GET";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
{
Console.Out.WriteLine("Error fetching data. Server returned status code: {0}", response.StatusCode);
}
else
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
var content = reader.ReadToEnd();
if (content.Equals("[]") || string.IsNullOrWhiteSpace(content) || string.IsNullOrEmpty(content))
{
MessagingCenter.Send(this, "Http", Username);
}
else
{
var result = JsonConvert.DeserializeObject<List<LoggedInUser>>(content);
var contactId = result[0].ContactID;
Application.Current.MainPage.Navigation.PushAsync(new DatabaseSyncPage { myId = contactId }, true);
}
}
}
}
else
{
MessagingCenter.Send(this, "Not Connected", Username);
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
DatabaseSyncPage.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace TBSMobileApplication.View
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class DatabaseSyncPage : ContentPage
{
public int myId { get; set; }
public DatabaseSyncPage ()
{
InitializeComponent ();
DisplayAlert("Message", Convert.ToString(myId), "ok");
}
}
}
If you want to send the int. First declare that in your DatabaseSyncPage
Like below
public partial class DatabaseSyncPage : ContentPage
{
public DatabaseSyncPage( int Id)
{
}
}
& when you are pushing your page in your code else block do like this
if (content.Equals("[]") || string.IsNullOrWhiteSpace(content) || string.IsNullOrEmpty(content))
{
MessagingCenter.Send(this, "Http", Username);
}
else
{
var result = JsonConvert.DeserializeObject<List<LoggedInUser>>(content);
var contactId = result[0].ContactID;
Application.Current.MainPage.Navigation.PushAsync(new DatabaseSyncPage(contactId), true);
}
I'm assuming that contactID is an int.
Create an additional constructor in your DatabaseSyncPage:
public DatabaseSyncPage (int contactID)
{
// TODO: Do something with your id
}
But this passes the data to the page, not the page model.
Are you using any kind of framework? It would probably be worth looking into that.
You can use xamrin.plugins.settings nuget package.

Web API Serialize/Deserialize Derived types

I have a Web API that returns a list of objects, when the client passes Accept application/json I want my globally registered json formatter to include TypeNameHandling for the derived types during serialization. However this doesn't work and I can't see why this shouldn't work ?
My objects
public class BaseClass
{
public int Id { get; set; }
}
public class SubClass : BaseClass
{
public string SubClassProp { get; set; }
}
public class SubClassA : SubClass
{
public string SubClassAProp { get; set; }
}
public class SubClassB : SubClass
{
public string SubClassBProp { get; set; }
}
WebApiConfig
public static void Register(HttpConfiguration config)
{
var formatters = GlobalConfiguration.Configuration.Formatters;
var jsonFormatter = formatters.JsonFormatter;
var settings = jsonFormatter.SerializerSettings;
settings.Formatting = Formatting.Indented;
settings.NullValueHandling = NullValueHandling.Ignore;
settings.TypeNameHandling = TypeNameHandling.Auto;
}
Web API Controller
public class MyController : ApiController
{
[HttpGet]
public async Task<IList<BaseClass>> GetClasses()
{
return new List<BaseClass>
{
new SubClassA
{
Id = 1,
SubClassProp = "SubClass",
SubClassAProp = "SubClassAProp"
},
new SubClassB
{
Id = 2,
SubClassProp = "SubClass",
SubClassBProp = "SubClassBProp"
}
};
}
}
Call from API Client in same solution
var client = new HttpClient() { BaseAddress = new Uri("uri goes here...")}
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var resp = await client.GetAsync("uri goes here..."));
var jsonContent = await resp.Content.ReadAsStringAsync();
var ListOfClasses = JsonConvert.DeserializeObject<IList<BaseClass>>(jsonContent, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto });
I'am expecting to get one element which is SubClassA and one that is SubClassB, but both is BaseClass ?
I also want it to be possible to Deserialize json to object in Post method.
And this should be possible for both json and xml

Windows universal app isolated storage - How to save and retrieve data?

I have this isolated storage helper and I need to use it to save and retrieve data from my universal app.
I don't know where to begin from. Should I maybe make an app and incorporate the helper class into it?
Here is my class:
using System.IO;
//using System.IO.IsolatedStorage;
using System.Runtime.Serialization.Json;
using System.Text;
public static class IsolatedStorageHelper
{
public static T GetObject<T>(string key)
{
var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
if (localSettings.Values.ContainsKey(key))
{
string serializedObject = localSettings.Values[key].ToString();
return Deserialize<T>(serializedObject);
}
return default(T);
}
public static void SaveObject<T>(string key, T objectToSave)
{
var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
string serializedObject = Serialize(objectToSave);
localSettings.Values[key] = serializedObject;
}
public static void DeleteObject(string key)
{
var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
localSettings.Values.Remove(key);
}
private static string Serialize(object objectToSerialize)
{
using (MemoryStream ms = new MemoryStream())
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(objectToSerialize.GetType());
serializer.WriteObject(ms, objectToSerialize);
ms.Position = 0;
using (StreamReader reader = new StreamReader(ms))
{
return reader.ReadToEnd();
}
}
}
private static T Deserialize<T>(string jsonString)
{
using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
return (T)serializer.ReadObject(ms);
}
}
}
use static SaveObject method and supply the 'person' entity and a key. Retrieve it later using GetObject.
But I think in this scenario you should use database sqlite and sqlite net package to save the entity.

Pass data serialized with Json.net library to the View and bind it with knockout

I am trying to send some serialized data to the view and bind it to the knockout code. I am using json.net library for serialization because I want to pass the constants of an enum to the view ( and not the underlying integers.) I am not sure how my controller returning Json data should look like. Here is the sample code:
My view model that will be serialized:
public class FranchiseInfoViewModel
{
public string FolderName { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public LobbyTemplateOptions LobbyTemplate { get; set; }
public List<LobbyTemplateOptions> LobbyTemplates { get; set; }
public void Initialize()
{
FolderName = "Test";
LobbyTemplate = LobbyTemplateOptions.G;
LobbyTemplates = new List<LobbyTemplateOptions>
{
LobbyTemplateOptions.G,
LobbyTemplateOptions.H,
LobbyTemplateOptions.I
};
Enum:
[JsonConverter(typeof(StringEnumConverter))]
public enum LobbyTemplateOptions
{
G = 7,
H = 8,
I = 9
}
My knockout code:
$(function () {
omega.FranchiseInfo = (function () {
var FolderName = ko.observable();
var LobbyTemplates = ko.observableArray([]);
$.getJSON("FranchiseData", function (data) {
FolderName(data.FolderName);
for (var i = 0; i < data.LobbyTemplate.length; i++) {
LobbyTemplates.push(data.LobbyTemplate[i]);
}
});
return {
folderName: FolderName,
lobbyTemplates: LobbyTemplates
}
} ());
ko.applyBindings(omega.FranchiseInfo);
})
}
I am wondering how my controller that passes serialized Json data to the view should look like as I have not used json.net and I am relatively new to programming:
Controller passing the Json data to the view:
public JsonResult FranchiseData()
{
FranchiseInfoViewModel franchiseInfoViewModel = new FranchiseInfoViewModel();
franchiseInfoViewModel.MapFranchiseInfoToFranchiseInfoViewModel();
string json = JsonConvert.SerializeObject(franchiseInfoViewModel);
// this is how I do it with the default Json serializer
// return Json(franchiseInfoViewModel, JsonRequestBehavior.AllowGet);
}
I would be very gratefull if somebody can post a working example of my controller. Thank You!
You need to implement JsonNetResult.
public class JsonNetResult : ActionResult
{
public Encoding ContentEncoding { get; set; }
public string ContentType { get; set; }
public object Data { get; set; }
public JsonSerializerSettings SerializerSettings { get; set; }
public Formatting Formatting { get; set; }
public JsonNetResult()
{
SerializerSettings = new JsonSerializerSettings();
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = !string.IsNullOrEmpty(ContentType)
? ContentType
: "application/json";
if (ContentEncoding != null)
response.ContentEncoding = ContentEncoding;
if (Data != null)
{
JsonTextWriter writer = new JsonTextWriter(response.Output) { Formatting = Formatting };
JsonSerializer serializer = JsonSerializer.Create(SerializerSettings);
serializer.Serialize(writer, Data);
writer.Flush();
}
}
}
To use it, in your case you need to rewrite controller method in this way:
public ActionResult FranchiseData()
{
FranchiseInfoViewModel franchiseInfoViewModel = new FranchiseInfoViewModel();
franchiseInfoViewModel.MapFranchiseInfoToFranchiseInfoViewModel();
JsonNetResult jsonNetResult = new JsonNetResult();
jsonNetResult.Formatting = Formatting.Indented;
jsonNetResult.Data = franchiseInfoViewModel;
return jsonNetResult;
}
(implementation of JsonNetResult above was taken this blog post
http://james.newtonking.com/archive/2008/10/16/asp-net-mvc-and-json-net.aspx )

Resources