I am using Dotmim.sync framework. I am trying to sync an mssql database with my xamarin android app's sqlite database. So I implemented the web proxy to reach the database from the android app.
The proxy starts fine, but then when I call the sync from the android app the Post method gives a null reference error, but I cannot find what is null.
In the ASP.NET Core web app's Startup file:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
// [Required]: To be able to handle multiple sessions
services.AddMemoryCache();
// [Required]: Get a connection string to your server data source
var connectionString = #"[my connection string]";
// [Required]: Tables list involved in the sync process
var tables = new string[] { "dbo.Album", "dbo.Artist", "dbo.Customer", "dbo.Invoice", "dbo.InvoiceItem", "dbo.Track" };
// [Required]: Add a SqlSyncProvider acting as the server hub.
services.AddSyncServer<SqlSyncChangeTrackingProvider>(connectionString, tables);
}
The SyncController:
[ApiController]
[Route("api/[controller]")]
public class SyncController : ControllerBase
{
private WebServerManager manager;
public SyncController(WebServerManager man) => this.manager = man;
[HttpPost]
public async Task Post()
{
await manager.HandleRequestAsync(this.HttpContext);
} //----> the Null error comes
[HttpGet]
public async Task Get() => await manager.HandleRequestAsync(this.HttpContext);
}
In the android app the sync function that is called:
public async Task SyncDatabase(string connString, Context context)
{
var handler = HttpClientHandlerService.GetInsecureHandler();
HttpClient httpClient = new HttpClient(handler);
httpClient.DefaultRequestHeaders.Host = $"localhost:44372";
var serverOrchestrator = new WebClientOrchestrator("https://10.0.2.2:44372/api/sync", client: httpClient);
// Second provider is using plain sqlite provider
var clientProvider = new SqliteSyncProvider(connString);
var agent = new SyncAgent(clientProvider, serverOrchestrator);
try
{
var result = await agent.SynchronizeAsync(); //---> error comes when this line is called
var output = result.ToString();
output = output.Replace("\n", " ").Replace("\t", " ").Replace("\r", " ");
Toast.MakeText(context, output, ToastLength.Long).Show();
}
catch (Exception e)
{
Toast.MakeText(context, e.Message, ToastLength.Long).Show();
}
}
Let me know what further information should I supply to solve this.
EDIT:
Calling from postman it gives this error: {"tn":"HttpHeaderMissingExceptiopn","m":"Header dotmim-sync-scope-name is missing."}
EDIT2:
Server orchestrator on the client side:
On the server side:
The details of the exception:
SOLUTION:
I tried the sync with a different database and tables, and that worked, so it was clear that dotmim has some problem with the tables I was using. So after lot of thinking I tried with a different schema name instead of dbo, since the other database that worked had something else. And it turns out the sync has some problem if the schema name is dbo, something gets mixed probably when it tries to create its own new tables. So use something different from dbo for schema.
Related
I am trying to run the TextToSpeech code from Google Cloud TextToSpeech Service.
Curently stuck at Authentication part referring link Authenticating as a service account
Below is the Code :
public class TexttoSpeech {
/** Demonstrates using the Text-to-Speech API. */
public static void getAudio() throws Exception {
// Instantiates a client
// Below Line is Point of Error in Code
try (TextToSpeechClient textToSpeechClient = TextToSpeechClient.create()) {
// Set the text input to be synthesized
SynthesisInput input = SynthesisInput.newBuilder().setText("Hello, World!").build();
// Build the voice request, select the language code ("en-US") and the ssml voice
//gender
// ("neutral")
VoiceSelectionParams voice =
VoiceSelectionParams.newBuilder()
.setLanguageCode("en-US")
.setSsmlGender(SsmlVoiceGender.NEUTRAL)
.build();
// Select the type of audio file you want returned
AudioConfig audioConfig =
AudioConfig.newBuilder().setAudioEncoding(AudioEncoding.MP3).build();
// Perform the text-to-speech request on the text input with the selected voice parameters and
// audio file type
SynthesizeSpeechResponse response =
textToSpeechClient.synthesizeSpeech(input, voice, audioConfig);
// Get the audio contents from the response
ByteString audioContents = response.getAudioContent();
byte[] audioArray=audioContents.toByteArray();
String converted= Base64.encodeBase64String(audioArray);
playAudio(converted);
// Write the response to the output file.
try (OutputStream out = new FileOutputStream("output.mp3")) {
out.write(audioContents.toByteArray());
System.out.println("Audio content written to file \"output.mp3\"");
}
}
}
public static void playAudio(String base64EncodedString){
try
{
String url = "data:audio/mp3;base64,"+base64EncodedString;
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(url);
mediaPlayer.prepare();
mediaPlayer.start();
}
catch(Exception ex){
System.out.print(ex.getMessage());
}
}
}
But getting below error on :
java.io.IOException: The Application Default Credentials are not available. They are available
if running in Google Compute Engine. Otherwise, the environment variable
GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials.
See https://developers.google.com/accounts/docs/application-default-credentials for more
information.
Also tried Explicit credentials :
#Throws(IOException::class)
fun authExplicit() {
val projectID = "texttospeech-12345" // dummy id
// val imageUri: Uri =
Uri.fromFile(File("file:\\android_asset\\service_account_file.json"))
// val path=File(imageUri.path).absolutePath
// You can specify a credential file by providing a path to GoogleCredentials.
// Otherwise credentials are read from the GOOGLE_APPLICATION_CREDENTIALS environment
variable.
val credentials =
GoogleCredentials.fromStream(mContext.resources.openRawResource(R.raw.service_account_file))
.createScoped(Lists.newArrayList("https://www.googleapis.com/auth/cloud-platform"))
val storage: Storage =
StorageOptions.newBuilder().setProjectId(projectID).setCredentials(credentials)
.build().service
println("Buckets:")
// Error at storage.lists()
val buckets: Page<Bucket> = storage.list()
for (bucket in buckets.iterateAll()) {
println(bucket.toString())
}
}
But on device it gives error like :
Error getting access token for service account:
Unable to resolve host "oauth2.googleapis.com": No address associated with hostname, iss:
xyz#texttospeech-12345.iam.serviceaccount.com
And on Emulator the error is :
xxxxxxxxx does not have storage.buckets.list access to the Google Cloud project.
Please let me know if you guys need something more.
Any suggestion will be appreciated
Thanks in Advance
Also if I run below command in Cloud SDK :
gcloud auth application-default login
I get this but I didnt understood what its trying to say
You can pass the credentials while creating the client connection.
TextToSpeechSettings settings = TextToSpeechSettings.newBuilder()
.setCredentialsProvider(FixedCredentialsProvider.create(authExplicit("JSON FILE PATH")))
.build();
try (TextToSpeechClient textToSpeechClient = TextToSpeechClient.create(settings)) {
// ... rest of your code
}
// ... rest of your code
And
public static GoogleCredentials authExplicit(String jsonPath) throws IOException {
GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(jsonPath))
.createScoped(Lists.newArrayList("https://www.googleapis.com/auth/cloud-platform"));
return credentials;
}
GoogleCredentials imported from Google Auth Library For Java OAuth2 HTTP
N.B You need to make sure you are able to fetch the JSON file in your application.
we have an app under xamarin android build with visual studio 2017.
this app works since three years without any problems.
since two weeks and I don't know why actually some device can't sync with our back end.
It's really strange because nothing has change in this part .
this error does not appear on all devices but on one or two from time to time
we use the dll httpClient for to sync the datas with our backend.
If i put a break point inside the postAsync I have an exception with this -> Cannot access a disposed object. Object name: 'System.Net.Sockets.NetworkStream
Any one has an idea about how to solve this ? also what does it meam ?
Here is it the code of the postAsync method :
thanks for our time and comment guys
public override HttpResult ExecutePost(Uri target, string body)
{
var client = new HttpClient();
client.MaxResponseContentBufferSize = MaxHttpResponseBufferSize;
try
{
var requestContent = new StringContent(body, RequestContentEncoding, RequestContentType);
var response = client.PostAsync(target, requestContent).Result;
if (response.IsSuccessStatusCode)
{
var content = response.Content.ReadAsStringAsync().Result;
return new HttpResult(content, null, null);
}
return new HttpResult(null, "Response is empty", response.StatusCode.ToString());
}
catch (Exception e)
{
return new HttpResult(null, "Problem with the HttpPost", e.Message);
}
}
I experienced the same issue. Have been battling for 6 hours on this issue.
If you read the error, I was getting (Failed to connect to localhost/127.0.0.1:7113). If you put localhost in your browser or swagger tool it will work but if you put https://127.0.0.1:7113/api/weatherforecast in your browser it will not work. It will give you a certificate problem.
So I think you have to resolve 127.0.0.1 to localhost with https certificate on your local dev machine.
I'm building a MAUI app with Visual Studio 2022 Preview.
So I solved this issue by deploying my API to AZURE.
Then update to the azure url for example:
string apiUrl = "https://weatherforecast.azurewebsites.net/api/weatherforecast";
and then it worked brilliantly. Like super brilliantly.
Here is my code:
public void LoginAsync()
{
HttpClient client = new HttpClient();
string apiUrl = "https://weatherforecast.azurewebsites.net/api/weatherforecast";
UserCredentials.EmailAddress = LoginUIEntity.EmailAddress;
UserCredentials.Password = LoginUIEntity.Password;
string serialized = JsonConvert.SerializeObject(UserCredentials);
var inputMessage = new HttpRequestMessage
{
Content = new StringContent(serialized, Encoding.UTF8, "application/json")
};
inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
try
{
var message = client.PostAsync(apiUrl, inputMessage.Content).Result;
if (message.IsSuccessStatusCode)
{
var apiResponse = message.Content.ReadAsStringAsync();
UserCredentials = JsonConvert.DeserializeObject<UserCredentials>(apiResponse.Result);
if (UserCredentials.IsValid)
{
UserCredentials.IsLoggedIn = true;
}
else
{
ErrorMessage = "Invalid credentials supplied.";
}
}
}
catch (Exception ex)
{
ErrorMessage = "An error has occurred. Please contact support if the error persists.";
}
}
}
thanks for the link your provide.
I've try up the buffer on the postasync / try to sync in wifi OR 3G / delete special character in json / ...
but nothing work
we have move the prod database to the test and try to sync the data to the test database with postman. with postman the result was ENTITY TOO LARGE !
Json is size > 1.2 mega and the default value inside IIS is set to 1 mega
Here is it the problem ...
thanks problem solve
I have a WPF application in VB.NET that already developed by my old colleagues. Now, my superior want to replace current platform by implementing the same concept to be run on the Android system. So, I've decided to use Xamarin Android .NET Standard.
I have searched for a way to consume WCF and the error throw before I'm asking but I'm still stuck at the same error.
I have set up the service references WCF on the android class. Given on solution, I have 2 projects:- MyProject and MyProject.Android
===========================================================================
WPF
Private Function EstablishConnect() As Boolean
Try
Dim context As InstanceContext = New InstanceContext(Me)
svrobj = New DisplayServicesClient(context, "DisplayTcpBinding")
Dim endpointAddress As New EndpointAddress(modUtility.ServerEndPointAddress)
svrobj.Endpoint.Address = endpointAddress
svrobj.Open()
SecondDiffFromServer = DateDiff(DateInterval.Second, Now, svrobj.GetDateTime)
Return True
Catch ex As Exception
WriteLog.Log(ex.ToString, True)
Return False
End Try
End Function
modUtility.ServerEndPointAddress get from INI:
net.tcp://localhost:8002/AppServ/WCFServices/Display
===========================================================================
XAMARIN FORMS
private async Task<bool> EstablishConnectAsync()
{
try
{
InstanceContext context = new InstanceContext(this);
svrobj = new DisplayServicesClient(DisplayServicesClientBase.EndpointConfiguration.DisplayTcpBinding); //, DisplayServicesClientBase.EndpointConfiguration.DisplayTcpBinding
EndpointAddress endpointAddress = new EndpointAddress(modUtility.ServerEndPointAddress);
svrobj.Endpoint.Address = endpointAddress;
await svrobj.OpenAsync();
modUtility.SecondDiffFromServer = (int)(DateTime.Now - await svrobj.GetDateTimeAsync()).TotalSeconds;
return true;
}
catch (Exception ex)
{
Device.BeginInvokeOnMainThread(() =>
{
ResultText.Text = "Unable to established connection with endpoint service. Ex-" + ex.Message;
});
return false;
}
}
modUtility.ServerEndPointAddress get from settings:
net.tcp://10.0.2.2:8002/AppServ/WCFServices/Display
I'm currently run android on emulator.
My code throw exception on any call to svrobj function. Below are the error that throw:-
The communication object System.ServiceModel.DuplexChannelFactory`1[AppServ.IDisplayServices] is not at created state but at Opening state.
The method or operation is not implemented.
Do I missing something or do I have implement wrong way?
Hi I've been trying to set up a simple Android app to send a query to a GraphQL server I set up on my localhost via Springboot. If I don't use the app to send a request, either through GraphiQL or Postman, everything is fine and I have absolutely no issues. It's only when I send the request in the app through an Apollo Client that I get a 422 error.
I've set up log statements in Springboot that hosts the GraphQL server to log the payload.
Here's the schema as defined in Springboot.
type Query {
bookById(id: ID): Book
}
type Book {
id: ID
name: String
pageCount: Int
author: Author
}
type Author {
id: ID
firstName: String
lastName: String
}
Here's the query as defined in AndroidStudio for the Apollo Client to work with.
query BookById($id : ID) {
bookById(id : $id){
name
author{
firstName
lastName
}
}}
Here's the code in Android Studio.
public class MainActivity extends AppCompatActivity {
private static final String BASE_URL = "http://xxx.xxx.xxx.xxx:8080/graphql";
private static final String TAG = "MainActivity";
private TextView textBox;
private Button queryButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textBox = (TextView) findViewById(R.id.plainbox);
queryButton = (Button) findViewById(R.id.queryButton);
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
ApolloClient apolloClient = ApolloClient.builder()
.serverUrl(BASE_URL)
.okHttpClient(okHttpClient)
.build();
// To make requests to our GraphQL API we must use an instance
// of a query or mutation class generated by Apollo.
Input<String> id = Input.fromNullable("book-1");
BookByIdQuery bq = BookByIdQuery.builder()
.id("book-1")
.build();
queryButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d(TAG, "REGISTERED CLICK");
Log.d(TAG, "Book Query: " + bq.queryDocument());
apolloClient.query(bq).enqueue(new
ApolloCall.Callback<BookByIdQuery.Data>() {
#Override
public void onResponse(#NotNull com.apollographql.apollo.api.Response<BookByIdQuery.Data> dataResponse){
Log.d(TAG, "Got Response: \n" + dataResponse.toString());
// changing UI must be on UI thread
textBox.setText(dataResponse.data().toString());
}
#Override
public void onFailure(#NotNull ApolloException a){
Log.d(TAG, "Failed, ApolloException " + a);
}
}); // end apolloClient query
}
});
}
Here's the log on the server side I get if making a request via GraphiQL or Postman.
DEBUG 13749 --- [nio-8080-exec-8] o.s.w.f.CommonsRequestLoggingFilter : Before request [uri=/graphql]
Here's the log when the request comes from Apollo in the app.
DEBUG 13749 --- [io-8080-exec-10] o.s.w.f.CommonsRequestLoggingFilter : Before request [uri=/graphql]
DEBUG 13749 --- [io-8080-exec-10] o.s.w.f.CommonsRequestLoggingFilter : REQUEST DATA : uri=/graphql;payload={"operationName":"BookById","variables":{"id":"book-1"},"query":"query BookById($id: ID) { bookById(id: $id) { __typename name author { __typename firstName lastName } }}"}]
Could the issue be related to the __typename attribute that Apollo is adding? Or could it be due to "id" being defined as a simple parameter in the server side schema but it being a variable in the Android Studio definition of the query?
I just expected to receive the response back with no issues since it seems to work every other way. Even if I type in the query manually into my web browser I have no issues getting the right response, it's only when working with Apollo Client in G̶r̶a̶p̶h̶Q̶L̶ Android Studio that this issue pops up and I'm at a complete loss as to why. I appreciate any help people can offer. Thanks in advance.
Update: So looking around some more it looks like when sending a query via ApolloClient it sends the query as an object instead of as a JSON string. Now I'm thinking that's probably the cause of the 422 error. I've also read that allowing my GraphQL server to accept objects in addition to JSON strings is something I must enable. I'm not really sure how to go about that though, so does anyone with experience with Spring Boot have any advice on how I could go about doing that? Thanks.
I have read on net tutorials that cloud can be used for storing data.So i wanted to ask that whether sql server 2005 table data be stored in amazon cloud.Can anyone give me the sample code to store data from sql server in amazon and retrieve it in android application?
Amazon gives you a server instance with the operating system specified by you. you can technically, install anything on it and host that.
What you should technically do is to take an instance of your desired specification from Amazon.
Write a simple web application (I would do a java webapp. For sure you can go for the same as you already are doing Android programming.) with connectivity to your DB and that has controllers to run your SQL queries and returns the values.
Here is some example code. This uses Spring just so you know. You can use plain MVC as well if you want do it simple to start with.
#RequestMapping ( value = "runquery" , method = RequestMethod.GET )
#ResponseBody
public void runQuery()
{
Statement lStatement = null;
Connection lConnection = null;
ResultSet lResultSet = null;
try
{
lConnection = DBAccess.getConnection();
lStatement = lConnection.createStatement();
lResultSet = lStatement.executeQuery( "select * from table" );
while ( lResultSet.next() )
{
mLogger.info("The result set is : "+lResultSet.toString());
}
}
catch( Exception e )
{
e.printStackTrace();
mLogger.error("Exception occurred while trying to runQuery : "+e.getMessage());
}
finally
{
DBAccess.closeResultSet( lResultSet );
DBAccess.closeStatement( lStatement );
DBAccess.closeDBConnection( lConnection );
}
}