mvvmcross showviewmodel byte[] as param - ios

I work with iOS throw Xamarin. I want's send byte[] from one viewModel to another using showviewmodel.
I invoke this Command:
private MvxCommand _editUser;
public System.Windows.Input.ICommand EditUser
{
get{
return new MvxCommand
(() => ShowViewModel<UserViewModel> (new {array = new byte[3]}));
}
}
and wait my byte[] as param in Init method on another viewModel(UserViewModel):
public void Init(byte[] array)
{
}
Constructor works good, but then does not reach the the Init method;
It throws an exception:
Failed to construct and initialize ViewModel for type AccountApp.Core.iOS.UserViewModel from locator MvxDefaultViewModelLocator - check MvxTrace for more information.
Any ideas?
Thanks.

Only strings, ints, doubles and bools are allowed in this constructor parameter passing at present. You would need to serialize this byte[] array to a string and then reconstruct it in the constructor of the view model you are navigating to.

Related

Neo4j - Custom converter for field of type List

I am trying to write a custom converter for a nested object so that this object gets saved as string in Neo4j database.
I am using #Convert annotation on my field and passing ImageConverter.class which is my AttributeConverter class.
Everything works fine as expected and I am able to save string representation of Image class in Neo4j db.
However, now instead of single image I want to have List<Image> as my nested field. In this case, putting #Convert(ImageConverter.class) doesn't work.
I see that there is a class called ConverterBasedCollectionConverter which gets used when I have a field of type List<LocalDateTime.
However, I couldn't find any exammples on how to use this class in case of custom converters.
Please can anyone help me with this or if there is any other approach to use custom converter on field of type List.
I am using Neo4j (version 3.4.1) and Spring-data-neo4j (5.0.10.RELEASE) in my application. I am also using OGM.
PS: I am aware that it is advised to store nested objects as separate node establishing a relationship with parent object. However, my use case demands that the object be stored as string property and not as separate node.
Regards,
V
It is not so difficult as I assumed it would be.
Given a class (snippet)
#NodeEntity
public class Actor {
#Id #GeneratedValue
private Long id;
#Convert(MyImageListConverter.class)
public List<MyImage> images = new ArrayList<>();
// ....
}
with MyImage as simple as can be
public class MyImage {
public String blob;
public MyImage(String blob) {
this.blob = blob;
}
public static MyImage of(String value) {
return new MyImage(value);
}
}
and a converter
public class MyImageListConverter implements AttributeConverter<List<MyImage>, String[]> {
#Override
public String[] toGraphProperty(List<MyImage> value) {
if (value == null) {
return null;
}
String[] values = new String[(value.size())];
int i = 0;
for (MyImage image : value) {
values[i++] = image.blob;
}
return values;
}
#Override
public List<MyImage> toEntityAttribute(String[] values) {
List<MyImage> images = new ArrayList<>(values.length);
for (String value : values) {
images.add(MyImage.of(value));
}
return images;
}
}
will print following debug output on save that I think is what you want:
UNWIND {rows} as row CREATE (n:Actor) SET n=row.props RETURN row.nodeRef as ref, ID(n) as id, {type} as type with params {type=node, rows=[{nodeRef=-1, props={images=[blobb], name=Jeff}}]}
especially the images part.
Test method for this looks like
#Test
public void test() {
Actor jeff = new Actor("Jeff");
String blobValue = "blobb";
jeff.images.add(new MyImage(blobValue));
session.save(jeff);
session.clear();
Actor loadedActor = session.load(Actor.class, jeff.getId());
assertThat(loadedActor.images.get(0).blob).isEqualTo(blobValue);
}
I am came up with a solution to my problem. So, in case you want another solution along with the solution provided by #meistermeier, you can use the below code.
public class ListImageConverter extends ConverterBasedCollectionConverter<Image, String>{
public ListImageConverter() {
super(List.class, new ImageConverter());
}
#Override
public String[] toGraphProperty(Collection<Image> values) {
Object[] graphProperties = super.toGraphProperty(values);
String[] stringArray = Arrays.stream(graphProperties).toArray(String[]::new);
return stringArray;
}
#Override
public Collection<Image> toEntityAttribute(String[] values) {
return super.toEntityAttribute(values);
}
}
ImageConverter class just implements AttributeConverter<Image, String> where I serialize and deserialize my Image object to/from json.
I chose to go with this approach because I had Image field in one object and List<Image> in another object. So just by changing #Convert(ListImageConverter.class) to #Convert(ImageConverter.class) I was able to save list as well as single object in Neo4j database.
Note: You can skip overriding toEntityAttribute method if you want. It doesn't add much value.
However you have to override toGraphProperty as within Neo4j code it checks for presence of declared method with name toGraphProperty.
Hope this helps someone!
Regards,
V

How to set argument to Ninject binder regarding on request header

Problem:
I have webapi serviss where almost every user has its own database instance to connect. So i have to set different connection string for each user. To recognize user i will pass specific Token into header. Regarding on this Token, system has to build and set differenct connection string into Data Access layer constructor (Order in this case)
Question:
Is it possible to pass argument to Ninject or any kind of IoC binder regarding on request header?
IOrders _orders;
public HomeController(IOrders order)
{
_orders = order;
}
Here is an Ninject binding, but as you can guess, HttpContext.Current is null.
private static void RegisterServices(IKernel kernel)
{
var some_value = HttpContext.Current.Request.Headers.GetValues("Token");
kernel.Bind<IOrders>()
.To<Orders>()
.WhenInjectedInto<HomeController>()
.WithConstructorArgument("Token", some_value);
}
Maybe there is much elegant way to do this using Controller Factory ?
I would create a service class that does this lookup for you. then inject this service into the Orders implementation.
public interface IRequestContext {
string ConnectionString {get;}
}
public class HttpHeaderRequestContext : IRequestContext {
public string ConnectionString {
get {
var token = HttpContext.Current.Request.Headers.GetValues("Token");
// .. lookup conn string based on token
}
}
}
public class Orders : IOrders {
public Orders(IRequestContext ctx) {
// create new connection w/ ctx.ConnectionString
}
}
using this method, the lookup of headers and connection strings is abstracted away from the implementation. this makes it easier to test and easier swap out with a different method of obtaining a connection string if the need arises.
After implementing Dave approach, i realized that i could solve this connection string injection by feeding HttpContext.Current into Ninject binding like this:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IOrders>()
.To<Orders>()
.WhenInjectedInto<HomeController>()
.WithConstructorArgument("smth", x => {
var token = HttpContext.Current.Request.Headers.Get("Token");
var _db = new SomeDataCxt();
var connStr = _db.DbStringRepository.GetByToken(token);
return connStr;
});
}

Mocking Task<IEnumerable<T>> with NSubstitute

I'm having issues trying to get NSubstitute to return an IEnumerable interface from a Task.
The factory I'm mocking:
public interface IWebApiFactory<T> : IDisposable
{
<T> GetOne(int id);
Task<IEnumerable<T>> GetAll();
Task<IEnumerable<T>> GetMany();
void SetAuth(string token);
}
The test method:
[TestMethod]
public async Task TestMutlipleUsersAsViewResult()
{
var employees = new List<EmployeeDTO>()
{
new EmployeeDTO(),
new EmployeeDTO()
};
// Arrange
var factory = Substitute.For<IWebApiFactory<EmployeeDTO>>();
factory.GetMany().Returns(Task.FromResult(employees));
}
The error I am getting is:
cannot convert from 'System.Threading.Tasks.Task> to System.Func>>
Is this an issue with me passing a list, as a posed to IEnumerable even though List is IEnumerable?
Edit:
These are the functions within NSubstitute
public static ConfiguredCall Returns<T>(this T value, Func<CallInfo, T> returnThis, params Func<CallInfo, T>[] returnThese);
public static ConfiguredCall Returns<T>(this T value, T returnThis, params T[] returnThese);
None of the overloads is a good match for the value you passed. The second signature, public static ConfiguredCall Returns<T>(this T value, T returnThis, params T[] returnThese); expect a value of the same type as the function's return type so it isn't the best match.
The simplest way to overcome this is to change the declaration of employees to IEnumerable<EmployeeDTO> :
IEnumerable<EmployeeDTO> employees = new List<EmployeeDTO>()
{
new EmployeeDTO(),
new EmployeeDTO()
};

Access the error message in ModelState error dictionary in ASP.net MVC unit test

I have added a key-value pair in the action result like this:
[HttpPost, Authorize]
public ActionResult ListFacilities(int countryid)
{
...
ModelState.AddModelError("Error","No facilities reported in this country!");
...
}
I have some cumbersome codes like these in a unit test to :
public void ShowFailforFacilities()
{
//bogus data
var facilities = controller.ListFacilities(1) as PartialViewResult;
Assert.AreSame("No facilities reported in this country!",
facilities.ViewData.ModelState["Error"].Errors.FirstOrDefault().ErrorMessage);
}
Of course, it works whenever I have only one error.
I don't like facilities.ViewData.ModelState["Error"].Errors.FirstOrDefault().ErrorMessage.
Is there an easier way for me to fetch the value from that dictionary?
Your FirstOrDefault isn't needed, because you'll get a NullReferenceException when accessing ErrorMessage. You can just use First().
Either way, I couldn't find any built-in solution. What I've done instead is create an extension method:
public static class ExtMethod
{
public static string GetErrorMessageForKey(this ModelStateDictionary dictionary, string key)
{
return dictionary[key].Errors.First().ErrorMessage;
}
}
Which works like this:
ModelState.GetErrorMessageForKey("error");
If you need better exception handling, or support for multiple errors, its easy to extend...
If you want this to be shorter you can create an extension method for the ViewData...
public static class ExtMethod
{
public static string GetModelStateError(this ViewDataDictionary viewData, string key)
{
return viewData.ModelState[key].Errors.First().ErrorMessage;
}
}
and usage:
ViewData.GetModelStateError("error");
Have you tried this?
// Note: In this example, "Error" is the name of your model property.
facilities.ViewData.ModelState["Error"].Value
facilities.ViewData.ModelState["Error"].Error

Why is ExecuteFunction method only available through base.ExecuteFunction in a child class of ObjectContext?

I'm trying to call ObjectContext.ExecuteFunction from my objectcontext object in the repository of my site.
The repository is generic, so all I have is an ObjectContext object, rather than one that actually represents my specific one from the Entity Framework.
Here's an example of code that was generated that uses the ExecuteFunction method:
[global::System.CodeDom.Compiler.GeneratedCode("System.Data.Entity.Design.EntityClassGenerator", "4.0.0.0")]
public global::System.Data.Objects.ObjectResult<ArtistSearchVariation> FindSearchVariation(string source)
{
global::System.Data.Objects.ObjectParameter sourceParameter;
if ((source != null))
{
sourceParameter = new global::System.Data.Objects.ObjectParameter("Source", source);
}
else
{
sourceParameter = new global::System.Data.Objects.ObjectParameter("Source", typeof(string));
}
return base.ExecuteFunction<ArtistSearchVariation>("FindSearchVariation", sourceParameter);
}
But what I would like to do is something like this...
public class Repository<E, C> : IRepository<E, C>, IDisposable
where E : EntityObject
where C : ObjectContext
{
private readonly C _ctx;
// ...
public ObjectResult<E> ExecuteFunction(string functionName, params[])
{
// Create object parameters
return _ctx.ExecuteFunction<E>(functionName, /* parameters */)
}
}
Anyone know why I have to call ExecuteFunction from base instead of _ctx?
Also, is there any way to do something like I've written out? I would really like to keep my repository generic, but with having to execute stored procedures it's looking more and more difficult...
Update: Here's what I've tried and the method does not show up in intellisense/it gives me an error when I try to compile with it
public ArtistSearchVariation findSearchVariation(string source)
{
System.Data.Objects.ObjextContext _ctx = new ObjectContext(/* connection string */);
System.Data.Objects.ObjectParameter sourceParam = new ObjectParameter("Source", source);
return _ctx.ExecuteFunction<ArtistSearchVariation>("FindSearchVariation", sourceParam);
}
Thanks,
Matt
You don't have to use base.ExecuteFunction, the ExecuteFunction method (and overloads) are public, not protected, so you can call them from external sites. Are you having trouble calling it?

Resources