I am learning flutter and trying to parse a json which is array or json objects like this.
[
{
"albumId": 1,
"id": 1,
"title": "accusamus beatae ad facilis cum similique qui sunt",
"url": "https://via.placeholder.com/600/92c952",
"thumbnailUrl": "https://via.placeholder.com/150/92c952"
},
{
"albumId": 1,
"id": 2,
"title": "reprehenderit est deserunt velit ipsam",
"url": "https://via.placeholder.com/600/771796",
"thumbnailUrl": "https://via.placeholder.com/150/771796"
},]
And here is my fetch function which fetches this data from server.
fetch() async{
var client = new http.Client();
try {
var uriResponse = await
client.get('https://jsonplaceholder.typicode.com/photos');
if(uriResponse.statusCode == 200){
var data = json.decode(uriResponse.body);//data is array of objects
List<Photo> pics= data.map((Map<String,dynamic> model)=> Photo.fromJson(model)).toList();
setState(() {
photos = data;
_isLoading = false;
});
}
} finally {
client.close();
}
}
But the line ;
List<Photo> pics= data.map((Map<String,dynamic> model)=> Photo.fromJson(model)).toList();
gives me error that:
ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: type '(Map<String, dynamic>, dynamic) => Photo' is not a subtype of type '(dynamic) => dynamic' of 'f'
Here is my Photo PODO class.
class Photo {
final int id;
final String title;
final String url;
final String thumbnailUrl;
Photo({this.id, this.title,this.url, this.thumbnailUrl});
factory Photo.fromJson(Map<String, dynamic> json) {
return Photo(
id: json['id'] as int,
title: json['title'] as String,
thumbnailUrl: json['thumbnailUrl'] as String,
url: json['url'] as String,
);
}
}
What i am doing wrong in the above code? Thanx in advance !
You can use quicktype it lets you copy in your JSON string and generates the Dart Objects
In my project I have done like this and its working
pics = (data as List).map((model) => Photo.fromJson(model)).toList();
Try using
pics = data.map((i)=>Photo.fromJson(i)).toList();
You are receiving an json array and not json object from server
try this if it didnt work make sure to print the the response body
Iterable<dynamic> l = json.decode(uriResponse.body);
List<Post> posts = l.map((model) => Post.fromJson(model)).toList();
When queue-ing a build manually using TFS2018 the shelveset name is not showing the source branch name in all cases. Sometimes it is filled out sometimes not. Since I am picking up build variables for the source branch
$(Build.SourceBranch)
$(Build.SourceBranchName)
They will be empty if the Shelveset name is empty.
Is it possible to set the shelveset name default as the sourcebranch using the API when creating the build definition?
Is there another build variable that I can use to get the source path for the currently built solution?
UPDATE So I am trying to update the source branches using the build api. However when called I get a
{StatusCode: 405, ReasonPhrase: 'Method Not Allowed', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Pragma: no-cache
X-TFS-ProcessId:
ActivityId:
X-TFS-Session:
X-VSS-E2EID:
X-FRAME-OPTIONS: SAMEORIGIN
X-VSS-UserData: :user
Persistent-Auth: true
Lfs-Authenticate: NTLM
X-Content-Type-Options: nosniff
Cache-Control: no-cache
Date: Fri, 09 Mar 2018 14:37:16 GMT
P3P: CP="CAO DSP COR ADMa DEV CONo TELo CUR PSA PSD TAI IVDo OUR SAMi BUS DEM NAV STA UNI COM INT PHY ONL FIN PUR LOC CNT"
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Content-Length: 93
Allow: GET
Content-Type: application/json; charset=utf-8
Expires: -1
}}
for the following code....
internal void UpdateSourceBranches(List<BuildDefinition> defs)
{
using (var handler = new HttpClientHandler { Credentials = new NetworkCredential(tfsUser, tfsPass) })
using (var client = new HttpClient(handler))
{
try
{
client.BaseAddress = new Uri(tfsServer);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
foreach (var def in defs)
{
var buildId = def.Id;
var sourceBranch = $"$/{def.Repository.Name}/{def.Project.Name}";
var parameters = new Dictionary<string, string> { { "BuildConfiguration", "release" },
{ "BuildPlatform", "x86|x64|ARM" },
{ "system.debug", "true" }
};
var jsonParams = JsonConvert.SerializeObject(parameters);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("id", buildId.ToString()),
new KeyValuePair<string, string>("sourceBranch", sourceBranch),
new KeyValuePair<string, string>("parameters", jsonParams)
});
var response = client.PostAsync($"DefaultCollection/{def.Repository.Name}/_apis/build/builds?api-version=3.0-preview.1", content);
var s = response.Result;
}
}
catch (Exception ex)
{
}
}
}
You should use Queue a build api to set SourceBranch, for example:
POST http://TFS2018:8080/tfs/DefaultCollection/{project}/_apis/build/builds?api-version=2.0
Content-Type: application/json
{
"definition": {
"id": 47
},
"sourceBranch":"$/CeceScrum/TestCaseProject",
"parameters":"{\"BuildConfiguration\":\"release\",\"BuildPlatform\":\"any cpu\",\"system.debug\":\"false\"}"
}
If you want to choose a shelveset to build, then the api looks like below:
POST http://TFS2018:8080/tfs/DefaultCollection/{project}/_apis/build/builds?api-version=2.0
Content-Type: application/json
{
"definition": {
"id": 47
},
"sourceBranch":"ceceShelveset;domain\\username",
"parameters":"{\"BuildConfiguration\":\"release\",\"BuildPlatform\":\"any cpu\",\"system.debug\":\"false\"}"
}
I'm trying to "run-app" my Grails app, but when it starts to add User and Admin via BootStrap it gives me this error
Creating admin user
Fresh Database. Creating ADMIN user.
2017-12-05 19:20:48.191 ERROR --- [ main] o.g.events.gorm.GormAnnotatedListener : Error triggering event [org.grails.datastore.mapping.engine.event.PreInsertEvent[source=org.grails.orm.hibernate.HibernateDatastore#6491006]] for listener [public void com.wolf.UserPasswordEncoderListener.onPreInsertEvent(org.grails.datastore.mapping.engine.event.PreInsertEvent)]: Property [password] is not a valid property of class com.wolf.User
java.lang.IllegalArgumentException: Property [password] is not a valid property of class com.wolf.User
at org.grails.datastore.mapping.reflect.FieldEntityAccess$FieldEntityReflector.getPropertyWriter(FieldEntityAccess.java:279)
at org.grails.datastore.mapping.reflect.FieldEntityAccess.setProperty(FieldEntityAccess.java:90)
at org.grails.datastore.mapping.engine.ModificationTrackingEntityAccess.setProperty(ModificationTrackingEntityAccess.groovy:41)
at com.wolf.UserPasswordEncoderListener.encodePasswordForEvent(UserPasswordEncoderListener.groovy:31)
at com.wolf.UserPasswordEncoderListener.onPreInsertEvent(UserPasswordEncoderListener.groovy:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1427)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:216)
at org.grails.events.gorm.GormAnnotatedListener$Trait$Helper.dispatch(GormAnnotatedListener.groovy:39)
at com.wolf.UserPasswordEncoderListener.dispatch(UserPasswordEncoderListener.groovy)
at org.grails.events.gorm.GormEventDispatcher.onPersistenceEvent(GormEventDispatcher.groovy:52)
at org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener.onApplicationEvent(AbstractPersistenceEventListener.java:51)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:393)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:347)
at org.grails.datastore.gorm.events.ConfigurableApplicationContextEventPublisher.publishEvent(ConfigurableApplicationContextEventPublisher.groovy:30)
at org.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor.publishEvent(ClosureEventTriggeringInterceptor.java:258)
at org.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor.onPreInsert(ClosureEventTriggeringInterceptor.java:166)
at org.hibernate.action.internal.EntityIdentityInsertAction.preInsert(EntityIdentityInsertAction.java:197)
at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:75)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:623)
at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:277)
at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:258)
at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:303)
at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:318)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:275)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:113)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:97)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
at org.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor.onSaveOrUpdate(ClosureEventTriggeringInterceptor.java:126)
at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:651)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:643)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:638)
at org.grails.orm.hibernate.AbstractHibernateGormInstanceApi$_performSave_closure3.doCall(AbstractHibernateGormInstanceApi.groovy:243)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1427)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
at groovy.lang.Closure.call(Closure.java:414)
at org.codehaus.groovy.runtime.ConvertedClosure.invokeCustom(ConvertedClosure.java:54)
at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:124)
at com.sun.proxy.$Proxy123.doInHibernate(Unknown Source)
at org.grails.orm.hibernate.GrailsHibernateTemplate.doExecute(GrailsHibernateTemplate.java:299)
at org.grails.orm.hibernate.GrailsHibernateTemplate.execute(GrailsHibernateTemplate.java:243)
at org.grails.orm.hibernate.GrailsHibernateTemplate.execute(GrailsHibernateTemplate.java:117)
at org.grails.orm.hibernate.AbstractHibernateGormInstanceApi.performSave(AbstractHibernateGormInstanceApi.groovy:242)
at org.grails.orm.hibernate.AbstractHibernateGormInstanceApi.save(AbstractHibernateGormInstanceApi.groovy:159)
at org.grails.datastore.gorm.GormEntity$Trait$Helper.save(GormEntity.groovy:151)
at org.grails.datastore.gorm.GormEntity$Trait$Helper$save$1.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
at com.wolf.User.save(User.groovy)
at com.wolf.User.save(User.groovy)
at org.grails.datastore.gorm.GormEntity$save.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at hubbub.BootStrap.createAdminUserIfRequired(BootStrap.groovy:141)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1427)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:384)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:69)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:52)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:154)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:158)
at hubbub.BootStrap$_closure1.doCall(BootStrap.groovy:22)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1427)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1087)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
at groovy.lang.Closure.call(Closure.java:414)
at groovy.lang.Closure.call(Closure.java:408)
at grails.util.Environment.evaluateEnvironmentSpecificBlock(Environment.java:535)
at grails.util.Environment.executeForEnvironment(Environment.java:528)
at grails.util.Environment.executeForCurrentEnvironment(Environment.java:504)
at org.grails.web.servlet.boostrap.DefaultGrailsBootstrapClass.callInit(DefaultGrailsBootstrapClass.java:74)
at org.grails.web.servlet.context.GrailsConfigUtils.executeGrailsBootstraps(GrailsConfigUtils.java:65)
at org.grails.plugins.web.servlet.context.BootStrapClassRunner.onStartup(BootStrapClassRunner.groovy:53)
at grails.boot.config.GrailsApplicationPostProcessor.onApplicationEvent(GrailsApplicationPostProcessor.groovy:261)
at grails.boot.config.GrailsApplicationPostProcessor.onApplicationEvent(GrailsApplicationPostProcessor.groovy)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:393)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:347)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:883)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:144)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at grails.boot.GrailsApp.run(GrailsApp.groovy:83)
at grails.boot.GrailsApp.run(GrailsApp.groovy:387)
at grails.boot.GrailsApp.run(GrailsApp.groovy:374)
at grails.boot.GrailsApp$run.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
at hubbub.Application.main(Application.groovy:8)
This started to happen when I installed Spring Security Core Plugin and changed my domain "User" property "password" with "passwordHash".
Here is the User domain:
package com.wolf
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import grails.compiler.GrailsCompileStatic
class User implements Serializable {
String loginId
String passwordHash
boolean enabled = true
boolean accountExpired
boolean accountLocked
boolean passwordExpired
Date dateCreated
static transients = ['springSecurityService']
static hasOne = [ profile: Profile ]
static hasMany = [ posts: Post, tags: Tag, following: User ]
Set<Role> getAuthorities() {
(UserRole.findAllByUser(this) as List<UserRole>)*.role as Set<Role>
}
static constraints = {
loginId size: 3..20, unique: true, blank: false
tags()
posts()
profile nullable: true
}
static mapping = {
posts sort: "dateCreated", order: "desc"
}
String toString() { return "User $loginId (id: $id)" }
String getDisplayString() { return loginId }
}
And last, here is the BootStrap code:
import static java.util.Calendar.*
class BootStrap {
def springSecurityService
def init = { servletContext ->
environments {
development {
if (!Post.count()) createSampleData()
}
test {
if (!Post.count()) createSampleData()
}
}
// Admin user is required for all environments
createAdminUserIfRequired()
}
private createSampleData() {
println "Creating sample data"
def now = new Date()
def chuck = new User(
loginId: "chuck_norris",
passwordHash: springSecurityService.encodePassword("highkick"),
profile: new Profile(fullName: "Chuck Norris", email: "chuck#nowhere.net"),
dateCreated: now).save(failOnError: true)
def glen = new User(
loginId: "glen",
passwordHash: springSecurityService.encodePassword("sheldon"),
profile: new Profile(fullName: "Glen Smith", email: "glen#nowhere.net"),
dateCreated: now).save(failOnError: true)
def peter = new User(
loginId: "peter",
passwordHash: springSecurityService.encodePassword("mandible"),
profile: new Profile(fullName: "Peter Ledbrook", email: "peter#nowhere.net"),
dateCreated: now).save(failOnError: true)
def frankie = new User(
loginId: "frankie",
passwordHash: springSecurityService.encodePassword("testing"),
profile: new Profile(fullName: "Frankie Goes to Hollywood", email: "frankie#nowhere.net"),
dateCreated: now).save(failOnError: true)
def sara = new User(
loginId: "sara",
passwordHash: springSecurityService.encodePassword("crikey"),
profile: new Profile(fullName: "Sara Miles", email: "sara#nowhere.net"),
dateCreated: now - 2).save(failOnError: true)
def phil = new User(
loginId: "phil",
passwordHash: springSecurityService.encodePassword("thomas"),
profile: new Profile(fullName: "Phil Potts", email: "phil#nowhere.net"),
dateCreated: now)
def dillon = new User(loginId: "dillon",
passwordHash: springSecurityService.encodePassword("crikey"),
profile: new Profile(fullName: "Dillon Jessop", email: "dillon#nowhere.net"),
dateCreated: now - 2).save(failOnError: true)
chuck.addToFollowing(phil)
chuck.addToPosts(content: "Been working my roundhouse kicks.")
chuck.addToPosts(content: "Working on a few new moves. Bit sluggish today.")
chuck.addToPosts(content: "Tinkering with the hubbub app.")
chuck.save(failOnError: true)
phil.addToFollowing(frankie)
phil.addToFollowing(sara)
phil.save(failOnError: true)
phil.addToPosts(content: "Very first post")
phil.addToPosts(content: "Second post")
phil.addToPosts(content: "Time for a BBQ!")
phil.addToPosts(content: "Writing a very very long book")
phil.addToPosts(content: "Tap dancing")
phil.addToPosts(content: "Pilates is killing me")
phil.save(failOnError: true)
sara.addToPosts(content: "My first post")
sara.addToPosts(content: "Second post")
sara.addToPosts(content: "Time for a BBQ!")
sara.addToPosts(content: "Writing a very very long book")
sara.addToPosts(content: "Tap dancing")
sara.addToPosts(content: "Pilates is killing me")
sara.save(failOnError: true)
dillon.addToPosts(content: "Pilates is killing me as well")
dillon.save(failOnError: true, flush: true)
// We have to update the 'dateCreated' field after the initial save to
// work around Grails' auto-timestamping feature. Note that this trick
// won't work for the 'lastUpdated' field.
def postsAsList = phil.posts as List
postsAsList[0].addToTags(user: phil, name: "groovy")
postsAsList[0].addToTags(user: phil, name: "grails")
postsAsList[0].dateCreated = now.updated(year: 2004, month: MAY)
postsAsList[1].addToTags(user: phil, name: "grails")
postsAsList[1].addToTags(user: phil, name: "ramblings")
postsAsList[1].addToTags(user: phil, name: "second")
postsAsList[1].dateCreated = now.updated(year: 2007, month: FEBRUARY, date: 13)
postsAsList[2].addToTags(user: phil, name: "groovy")
postsAsList[2].addToTags(user: phil, name: "bbq")
postsAsList[2].dateCreated = now.updated(year: 2009, month: OCTOBER)
postsAsList[3].addToTags(user: phil, name: "groovy")
postsAsList[3].dateCreated = now.updated(year: 2011, month: MAY, date: 1)
postsAsList[4].dateCreated = now.updated(year: 2011, month: DECEMBER, date: 4)
postsAsList[5].dateCreated = now.updated(year: 2012, date: 10)
phil.save(failOnError: true)
postsAsList = sara.posts as List
postsAsList[0].dateCreated = now.updated(year: 2007, month: MAY)
postsAsList[1].dateCreated = now.updated(year: 2008, month: APRIL, date: 13)
postsAsList[2].dateCreated = now.updated(year: 2008, month: APRIL, date: 24)
postsAsList[3].dateCreated = now.updated(year: 2011, month: NOVEMBER, date: 8)
postsAsList[4].dateCreated = now.updated(year: 2011, month: DECEMBER, date: 4)
postsAsList[5].dateCreated = now.updated(year: 2012, month: AUGUST, date: 1)
sara.dateCreated = now - 2
sara.save(failOnError: true)
dillon.dateCreated = now - 2
dillon.save(failOnError: true, flush: true)
}
private createAdminUserIfRequired() {
println "Creating admin user"
if (!User.findByLoginId("admin")) {
println "Fresh Database. Creating ADMIN user."
def profile = new Profile(email: "admin#yourhost.com", fullName: "Administrator")
def adminRole = new Role(authority: "ROLE_ADMIN").save(failOnError: true)
def adminUser = new User(
loginId: "admin",
passwordHash: springSecurityService.encodePassword("secret"),
profile: profile,
enabled: true).save(failOnError: true)
UserRole.create adminUser, adminRole, true
}
else {
println "Existing admin user, skipping creation"
}
}
}
I don't know if it's related to Database Migration Plugin, but I checked every domain and no one has "password" as property.
I found the solution... in "main/groovy/package/UserPasswordEncoderListener "encorePasswordForEvent" method had the old property "password" instead of "passwordHash".
Here's the method with old "password" property:
private void encodePasswordForEvent(AbstractPersistenceEvent event) {
if (event.entityObject instanceof User) {
User u = event.entityObject as User
if (u.passwordHash && ((event instanceof PreInsertEvent) || (event instanceof PreUpdateEvent && u.isDirty('password')))) {
event.getEntityAccess().setProperty('password', encodePassword(u.passwordHash))
}
}
}
Here's with the new "passwordHash" property:
private void encodePasswordForEvent(AbstractPersistenceEvent event) {
if (event.entityObject instanceof User) {
User u = event.entityObject as User
if (u.passwordHash && ((event instanceof PreInsertEvent) || (event instanceof PreUpdateEvent && u.isDirty('passwordHash')))) {
event.getEntityAccess().setProperty('passwordHash', encodePassword(u.passwordHash))
}
}
}
When opening up the android application via a link, the android application crashes, with a NullReferenceExcetpion.
The NRE happens in the base.OnCreate(bundle) method. The base is of type MvxFragmentCompatActivity. I have also tried this with a standard MvxActivity.
I have had a look at the following questions (but to no avail)
ViewModel null when Activity started from IntentFilter
Open MvvmCross app via link with data
The Activity
[Activity(...)]
[IntentFilter(new[] { Intent.ActionView }, DataScheme = "https", DataHost = "my.link.com", DataPathPrefix = "/some/path/", Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable })]
public class MyActivity : MvxFragmentCompatActivity<MyViewModel>
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
//Other code here (never reached when triggered by IntentFilter)
}
}
The stack trace
Caused by: md52ce486a14f4bcd95899665e9d932190b.JavaProxyThrowable: System.NullReferenceException: Object reference not set to an instance of an object
04-15 12:37:45.361 E/AndroidRuntime(26519): at MvvmCross.Platform.Mvx.Resolve[TService] () <0x9dcd9978 + 0x00038> in <filename unknown>:0
04-15 12:37:45.361 E/AndroidRuntime(26519): at MvvmCross.Binding.Droid.BindingContext.MvxAndroidBindingContextHelpers.Current[T] () <0x9dcd9930 + 0x0001b> in <filename unknown>:0
04-15 12:37:45.361 E/AndroidRuntime(26519): at MvvmCross.Binding.Droid.BindingContext.MvxAndroidBindingContextHelpers.Current () <0x9dcd9910 + 0x0000f> in <filename unknown>:0
04-15 12:37:45.361 E/AndroidRuntime(26519): at MvvmCross.Binding.Droid.Views.MvxLayoutInflater.Inflate (Int32 resource, Android.Views.ViewGroup root, Boolean attachToRoot) <0x9dcd7800 + 0x00033> in <filename unknown>:0
04-15 12:37:45.361 E/AndroidRuntime(26519): at Android.Views.LayoutInflater.n_Inflate_ILandroid_view_ViewGroup_Z (IntPtr jnienv, IntPtr native__this, Int32 resource, IntPtr native_root, Boolean attachToRoot) <0x9dcd7780 + 0x00063> in <filename unknown>:0
04-15 12:37:45.361 E/AndroidRuntime(26519): at (wrapper dynamic-method) System.Object:a2381224-dbcc-42b0-9aea-a687067e2004 (intptr,intptr,int,intptr,bool)
04-15 12:37:45.361 E/AndroidRuntime(26519): --- End of stack trace from previous location where exception was thrown ---
04-15 12:37:45.361 E/AndroidRuntime(26519): at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () <0x9dcdc6b8 + 0x0002b> in <filename unknown>:0
04-15 12:37:45.361 E/AndroidRuntime(26519): at Android.Runtime.JNIEnv.CallNonvirtualVoidMethod (IntPtr jobject, IntPtr jclass, IntPtr jmethod, Android.Runtime.JValue* parms) <0x9dd046f0 + 0x000b3> in <filename unknown>:0
04-15 12:37:45.361 E/AndroidRuntime(26519): at Android.Support.V4.App.FragmentActivity.OnCreate (Android.OS.Bundle savedInstanceState) <0x9dcd6608 + 0x0014f> in <filename unknown>:0
04-15 12:37:45.361 E/AndroidRuntime(26519): at MvvmCross.Droid.Support.V7.AppCompat.MvxEventSourceAppCompatActivity.OnCreate (Android.OS.Bundle bundle) <0x9dcd5850 + 0x00037> in <filename unknown>:0
04-15 12:37:45.361 E/AndroidRuntime(26519): at MyMobileApp.Droid.Activities.MyActivity.OnCreate (Android.OS.Bundle bundle) <0x9dcd5400 + 0x0001b> in <filename unknown>:0
04-15 12:37:45.361 E/AndroidRuntime(26519): at Android.Support.V4.App.FragmentActivity.n_OnCreate_Landroid_os_Bundle_ (IntPtr jnienv, IntPtr native__this, IntPtr native_savedInstanceState) <0x9dcd5380 + 0x00057> in <filename unknown>:0
04-15 12:37:45.361 E/AndroidRuntime(26519): at (wrapper dynamic-method) System.Object:e50a07b6-601f-425e-bac2-dd61e65b301f (intptr,intptr,intptr)
04-15 12:37:45.361 E/AndroidRuntime(26519): at md5af86c8db51f1d1641c99147539ead00a.MyActivity.n_onCreate(Native Method)
04-15 12:37:45.361 E/AndroidRuntime(26519): at md5af86c8db51f1d1641c99147539ead00a.MyActivity.onCreate(MyActivity.java:43)
04-15 12:37:45.361 E/AndroidRuntime(26519): at android.app.Activity.performCreate(Activity.java:5990)
04-15 12:37:45.361 E/AndroidRuntime(26519): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
04-15 12:37:45.361 E/AndroidRuntime(26519): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
04-15 12:37:45.361 E/AndroidRuntime(26519): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
04-15 12:37:45.361 E/AndroidRuntime(26519): at android.app.ActivityThread.access$800(ActivityThread.java:151)
04-15 12:37:45.361 E/AndroidRuntime(26519): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
04-15 12:37:45.361 E/AndroidRuntime(26519): at android.os.Handler.dispatchMessage(Handler.java:102)
04-15 12:37:45.361 E/AndroidRuntime(26519): at android.os.Looper.loop(Looper.java:135)
04-15 12:37:45.361 E/AndroidRuntime(26519): at android.app.ActivityThread.main(ActivityThread.java:5254)
I think this has to do with: https://github.com/MvvmCross/MvvmCross/issues/1192
Try something like this:
protected override void OnCreate(Bundle bundle)
{
var setup = MvxAndroidSetupSingleton.EnsureSingletonAvailable(ApplicationContext);
setup.EnsureInitialized();
base.OnCreate(bundle);
}
Simply put serializing data in the "application/json; charset=utf-8" format misbehaves in MVC3 (and possibly older versions). What happens is a nullable numbers all end up null, and numbers of "decimal" type end up 0 when serializing them inside a javascript object (to JSON) and leaving them as numbers and not strings.
Here is the example code that illustrates this misbehavior
- - - this example was created using jquery-1.4.4.js and jquery.json-2.2.js - - - -
HomeController.cs:
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.SaveUrl = Url.Action("Save", "Home", new { inspectionFormID = Guid.Empty }, Request.Url.Scheme);
return View();
}
public JsonResult Save(Guid inspectionFormID, JsonTest result)
{
return Json(result);
}
public class JsonTest
{
public double Double { get; set; }
public double? DoubleNull { get; set; }
public decimal Decimal { get; set; }
public decimal? DecimalNull { get; set; }
public Double Double2 { get; set; }
public Double? Double2Null { get; set; }
public Decimal Decimal2 { get; set; }
public Decimal? Decimal2Null { get; set; }
public Single Single { get; set; }
public Single? SingleNull { get; set; }
public float Float { get; set; }
public float? FloatNull { get; set; }
public int Int { get; set; }
public int? IntNull { get; set; }
public Int64 Int64 { get; set; }
public Int64? Int64Null { get; set; }
}
}
Index.cshtml:
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<b>#ViewBag.SaveUrl</b>
<br />
<hr />
<br />
<h3>Integral Numbers</h3>
<button type="button" class="a">Clicky</button>
<div></div>
<h3>Decimal Numbers (xx.0)</h3>
<button type="button" class="b">Clicky</button>
<div></div>
<h3>Decimal Numbers (xx.5)</h3>
<button type="button" class="c">Clicky</button>
<div></div>
<h3>Integral Numbers as strings</h3>
<button type="button" class="d">Clicky</button>
<div></div>
<h3>Decimal Numbers as strings (xx.5)</h3>
<button type="button" class="e">Clicky</button>
<div></div>
<script type="text/javascript">
$(function () {
var saveUrl = '#ViewBag.SaveUrl';
var printObj = function (inObj, destx) {
var dest = $('<table>').appendTo(destx),
dst1 = $('<tr>').appendTo(dest),
dst2 = $('<tr>').appendTo(dest);
for (var p in inObj) {
$('<th>', { text: p, css: { color: 'red', padding: '3px', background: '#dedede' } }).appendTo(dst1);
$('<td>', { text: inObj[p] || 'null' }).appendTo(dst2);
}
};
$('button.a').click(function () {
var curr = $(this).next(),
outR = {
Double: 12,
DoubleNull: 13,
Decimal: 14,
DecimalNull: 15,
Double2: 16,
Double2Null: 17,
Decimal2: 18,
Decimal2Null: 19,
Single: 20,
SingleNull: 21,
Float: 22,
FloatNull: 23,
Int: 24,
IntNull: 25,
Int64: 26,
Int64Null: 27
};
$('<hr />').appendTo(curr);
printObj(outR, curr);
$.ajax({
type: 'POST',
url: saveUrl,
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: $.toJSON({
inspectionFormID: 'fbde6eda-dde6-4ba9-b82d-3a35349415f0',
result: outR
}),
error: function (jqXHR, textStatus, errorThrown) {
alert('save failed');
},
success: function (data, textStatus, jqXHR) {
printObj(data, curr);
}
});
});
$('button.b').click(function () {
var curr = $(this).next(),
outR = {
Double: 12.0,
DoubleNull: 13.0,
Decimal: 14.0,
DecimalNull: 15.0,
Double2: 16.0,
Double2Null: 17.0,
Decimal2: 18.0,
Decimal2Null: 19.0,
Single: 20.0,
SingleNull: 21.0,
Float: 22.0,
FloatNull: 23.0,
Int: 24.0,
IntNull: 25.0,
Int64: 26.0,
Int64Null: 27.0
};
$('<hr />').appendTo(curr);
printObj(outR, curr);
$.ajax({
type: 'POST',
url: saveUrl,
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: $.toJSON({
inspectionFormID: 'fbde6eda-dde6-4ba9-b82d-3a35349415f0',
result: outR
}),
error: function (jqXHR, textStatus, errorThrown) {
alert('save failed');
},
success: function (data, textStatus, jqXHR) {
printObj(data, curr);
}
});
});
$('button.c').click(function () {
var curr = $(this).next(),
outR = {
Double: 12.5,
DoubleNull: 13.5,
Decimal: 14.5,
DecimalNull: 15.5,
Double2: 16.5,
Double2Null: 17.5,
Decimal2: 18.5,
Decimal2Null: 19.5,
Single: 20.5,
SingleNull: 21.5,
Float: 22.5,
FloatNull: 23.5,
Int: 24.5,
IntNull: 25.5,
Int64: 26.5,
Int64Null: 27.5
};
$('<hr />').appendTo(curr);
printObj(outR, curr);
$.ajax({
type: 'POST',
url: saveUrl,
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: $.toJSON({
'inspectionFormID': 'fbde6eda-dde6-4ba9-b82d-3a35349415f0',
'result': outR
}),
error: function (jqXHR, textStatus, errorThrown) {
alert('save failed');
},
success: function (data, textStatus, jqXHR) {
printObj(data, curr);
}
});
});
$('button.d').click(function () {
var curr = $(this).next(),
outR = {
Double: '12',
DoubleNull: '13',
Decimal: '14',
DecimalNull: '15',
Double2: '16',
Double2Null: '17',
Decimal2: '18',
Decimal2Null: '19',
Single: '20',
SingleNull: '21',
Float: '22',
FloatNull: '23',
Int: '24',
IntNull: '25',
Int64: '26',
Int64Null: '27'
};
$('<hr />').appendTo(curr);
printObj(outR, curr);
$.ajax({
type: 'POST',
url: saveUrl,
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: $.toJSON({
'inspectionFormID': 'fbde6eda-dde6-4ba9-b82d-3a35349415f0',
'result': outR
}),
error: function (jqXHR, textStatus, errorThrown) {
alert('save failed');
},
success: function (data, textStatus, jqXHR) {
printObj(data, curr);
}
});
});
$('button.e').click(function () {
var curr = $(this).next(),
outR = {
Double: '12.5',
DoubleNull: '13.5',
Decimal: '14.5',
DecimalNull: '15.5',
Double2: '16.5',
Double2Null: '17.5',
Decimal2: '18.5',
Decimal2Null: '19.5',
Single: '20.5',
SingleNull: '21.5',
Float: '22.5',
FloatNull: '23.5',
Int: '24.5',
IntNull: '25.5',
Int64: '26.5',
Int64Null: '27.5'
};
$('<hr />').appendTo(curr);
printObj(outR, curr);
$.ajax({
type: 'POST',
url: saveUrl,
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: $.toJSON({
'inspectionFormID': 'fbde6eda-dde6-4ba9-b82d-3a35349415f0',
'result': outR
}),
error: function (jqXHR, textStatus, errorThrown) {
alert('save failed');
},
success: function (data, textStatus, jqXHR) {
printObj(data, curr);
}
});
});
});
</script>
Run it click each button once, and look at the before/after. Thanks in advance for any insight, correction or help that you can provide to resolve this issue.
you can also download the code samples listed above and see the official bug report for this at this link: http://aspnet.codeplex.com/workitem/8114
EDIT: I am including this image to help everyone get what's going on here
click here to see the screenshot of the included example running
Basically: { propertyThatIsADecimal: 54 } becomes { propertyThatIsADecimal: 0 } on the server for multiple different number types in varying scenarios which there doesn't seem to be any rhyme or reason to.
The reason is because when MVC encounters a number it treats it as an Int32. As such there are no converters, for some reason, from Int32 to say a Decimal or a Nullable<Int64>. There are a couple ways around this issue. Strings, as you already have in your project or to create a custom model binder.
public class JsonTestModelBinder : IModelBinder {
public virtual object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
JsonTest result = new JsonTest();
foreach (var property in typeof(JsonTest).GetProperties()) {
//the value provider starts with the name of the property we're binding to
//i'm not sure if this changed or not as i don't recall having to do this
//before - you can remove "result." if your needs don't require it
var value = bindingContext.ValueProvider.GetValue("result." + property.Name);
if (value != null && value.RawValue != null) {
//are we binding to a nullable?
if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
property.SetValue(result, Convert.ChangeType(value.AttemptedValue, new NullableConverter(property.PropertyType).UnderlyingType), null);
} else {
property.SetValue(result, Convert.ChangeType(value.AttemptedValue, property.PropertyType), null);
}
}
}
return result;
}
}
I'm not entirely sure why we still can't convert from Int32 to Decimal but the problem exists within MVC's ValueProviderResult.ConvertSimpleType. It's using TypeDescriptor.GetConverter(your propertyType) and there's no conversions available for those types.
I don't like this particular method but it's the only one available to you for now.
I only glanced at your question, so I apologize if this doesn't apply. But I remember encountering a few issues with Json:
Was this a binding issue? If so, maybe you can implement a custom binding. (Apparently MVC3 uses the JsonFactory already).
I can't remember the issue, but I needed to add JsonRequestBehaviour.AllowGet when making jQuery calls using .getJSON.
Does it matter that you don't have a [HttpGet] or [HttpPost] on your Save method?
I downloaded your code and ran the example. When I clicked the button I received a JavaScript error (Microsoft JScript runtime error: Object doesn't support this property or method) at:
$.ajax({
type: 'POST',
url: saveUrl,
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: $.toJSON({
inspectionFormID: 'fbde6eda-dde6-4ba9-b82d-3a35349415f0',
result: outR
}),
error: function (jqXHR, textStatus, errorThrown) {
alert('save failed');
},
success: function (data, textStatus, jqXHR) {
printObj(data, curr);
}
});
It was also not clear to me from your description what the "before/after" was supposed to be. Can you distill this down to the absolute simplest case with just a single example? I'm assuming that if we can figure it out for that case, then it will apply to the rest.