Monday, November 26, 2018

Cordova build errors and fixes

Creating a new cordova project

This is where we start to create a new project.
cordova create hello com.example.hello HelloWorld
Adding Android platform.
C:\hello>cordova platform add android
Using cordova-fetch for cordova-android@~7.1.1
Adding android project...
Creating Cordova project for the Android platform:
        Path: platforms\android
        Package: com.example.hello
        Name: hello
        Activity: MainActivity
        Android target: android-27
Android project created with cordova-android@7.1.2
Android Studio project detected
Android Studio project detected
Discovered plugin "cordova-plugin-whitelist" in config.xml. Adding it to the project
Installing "cordova-plugin-whitelist" for android

Adding cordova-plugin-whitelist to package.json
Saved plugin info for "cordova-plugin-whitelist" to config.xml
--save flag or autosave detected
Saving android@~7.1.2 into config.xml file ...

Run the following command to build the project for all platforms

cordova build

Build Errors

ERROR1:
Error occurred during initialization of VM
Could not reserve enough space for 2097152KB object heap
Fix
Go to Start->Control Panel->System->Advanced(tab)->Environment Variables->System
Variables->New:
Variable name: _JAVA_OPTIONS   
Variable value: -Xmx512M

Variable name: Path  
Variable value: ;C:\Program Files\Java\jre6\bin;F:\JDK\bin;  
Change this to your appropriate path.
Restart computer!
ERROR2:
File C:\Users\oktay\.android\repositories.cfg could not be loaded.
Checking the license for package Android SDK Build-Tools 26.0.2 in C:\Program Files (x86)\Android\android-sdk\licenses

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring project ':CordovaLib'.
> You have not accepted the license agreements of the following SDK components:
  [Android SDK Build-Tools 26.0.2].
  Before building your project, you need to accept the license agreements and complete the installation of the missing components using the Android Studio SDK Manager.
  Alternatively, to learn how to transfer the license agreements from one workstation to another, go to http://d.android.com/r/studio-ui/export-licenses.html
Fix
Create license file in %ANDROID_HOME%
mkdir "%ANDROID_HOME%\licenses"
echo |set /p="8933bad161af4178b1185d1a37fbf41ea5269c55" > "%ANDROID_HOME%\licenses\android-sdk-license"
ERROR3:
Warning: License for package Android SDK Build-Tools 26.0.2 not accepted.
Fix
Manually accept the license.
C:\Program Files (x86)\Android\android-sdk\tools\bin>sdkmanager --update && yes | sdkmanager --licenses
ERROR4:
Checking the license for package Android SDK Build-Tools 26.0.2 in C:\Program Files (x86)\Android\android-sdk\licenses
License for package Android SDK Build-Tools 26.0.2 accepted.
Preparing "Install Android SDK Build-Tools 26.0.2 (revision: 26.0.2)".
Warning: Failed to read or create install properties file.

The SDK directory (C:\Program Files (x86)\Android\android-sdk) is not writeable,
  please update the directory permissions.
Fix
Give Full permission to Everyone for sdk folder ( C:\Program Files (x86)\Android\android-sdk)

Giving full permission to "ALL APPLICATION PACKAGES" and "TrustedInstaller" didn't solve my problem.
Checking the license for package Android SDK Build-Tools 26.0.2 in C:\Program Files (x86)\Android\android-sdk\licenses
License for package Android SDK Build-Tools 26.0.2 accepted.
Preparing "Install Android SDK Build-Tools 26.0.2 (revision: 26.0.2)".
...
BUILD SUCCESSFUL in 2m 55s
46 actionable tasks: 46 executed
Built the following apk(s):
        C:\hello\platforms\android\app\build\outputs\apk\debug\app-debug.apk

Build project and Emulate in Andorid

cordova build
cordova emulate android
APPENDIX: A WARNING
C:\Program Files (x86)\Android\android-sdk\tools\bin>sdkmanager
Picked up _JAVA_OPTIONS: -Xmx512M
Warning: cvc-pattern-valid: Value '' is not facet-valid with respect to pattern '[a-zA-Z0-9_-]+' for type 'idType'.
Warning: cvc-type.3.1.3: The value '' of element 'id' is not valid.
Warning: cvc-pattern-valid: Value '' is not facet-valid with respect to pattern '[a-zA-Z0-9_-]+' for type 'idType'.
Warning: cvc-type.3.1.3: The value '' of element 'id' is not valid.
Warning: File C:\Users\oktay\.android\repositories.cfg could not be loaded.
[=======================================] 100% Computing updates...
Error resolved by creating an empty repositories.cfg file.

Cordova installation info is here

Wednesday, November 14, 2018

Web Api Post Types (C#)

You can find some implementations of Web Api Post types here.
Model

public class Model
{
 public string Name { get; set; }
 public string Id { get; set; }

 public string Save()
 {
  return "Saved";
 }
}

1. Post Raw

Web Api

[HttpPost]
public async Task PostRaw()
{
 string json = await Request.Content.ReadAsStringAsync();

 Model model = Newtonsoft.Json.JsonConvert.DeserializeObject(json);

 return model.Save();
}
Request
POST http://localhost:63693/api/test/PostRaw HTTP/1.1
Content-Type: application/json

{"Id":"1","Name":"Model1"}

2. FromBody

Web Api

[HttpPost]
public string PostFromBody([FromBody]string body)
{
 Model model = Newtonsoft.Json.JsonConvert.DeserializeObject(body);

 return model.Save();
}
Request
Escape json: "{\"Id\":\"1\",\"Name\":\"Model1\"}"
POST http://localhost:63693/api/test/PostModel HTTP/1.1
Content-Type: application/json

"{\"Id\":\"1\",\"Name\":\"Model1\"}"
or
POST http://localhost:63693/api/test/PostFromBody HTTP/1.1
Content-Type: application/x-www-form-urlencoded

%7B%22body%22=%7B%22Id%22%3A%221%22%2C%22Name%22%3A%22Model1%22%7D%7D

3. Class parameter

Web Api

[HttpPost]
public string PostModel(Model model)
{
 return model.Save();
}
Request
POST http://localhost:63693/api/test/PostModel HTTP/1.1
Content-Type: application/json

{"Id":"1","Name":"Model1"}

4. String parameter + Request.Content

Web Api

[HttpPost]
public string PostModelJson(string key)
{
 //You may check key here...

 var contentType = Request.Content.Headers.ContentType.MediaType;
 var body = Request.Content.ReadAsStringAsync().Result;

 Model model = null;

 if (contentType == "application/json")
 {
  model = Newtonsoft.Json.JsonConvert.DeserializeObject(body);

  return model.Save();
 }
 else
  throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
Request
POST http://localhost:63693/api/test/PostModelJson?key=1 HTTP/1.1
Content-Type: application/json

{"Id":"1","Name":"Model1"}

5. Post uri parameter

Web Api

[HttpPost]
public string PostModelFromUri([FromUri]Model model)
{
 return model.Save();
}
Request
POST http://localhost:63693/api/test/PostModelFromUri?id=1&name=Model1 HTTP/1.1

6. Multipart Form Data

Web Api

[HttpPost]
public string PostMultipart()
{
 var contentType = Request.Content.Headers.ContentType.MediaType;

 if (contentType == "multipart/form-data")
 {
  var parts = Request.Content.ReadAsMultipartAsync().Result;

  var contents = parts.Contents;
  Model model = new Model();

  foreach (StreamContent item in contents)
  {
   if (item.Headers.ContentDisposition.Name.Trim('"') == "Id")
    model.Id = item.ReadAsStringAsync().Result;
   else if (item.Headers.ContentDisposition.Name.Trim('"') == "Name")
    model.Name = item.ReadAsStringAsync().Result;
  }

  return model.Save();
 }
 else
  throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);            
}
Request
POST http://localhost:63693/api/test/PostMultipart HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryrKvJKnAHtuVvEERM

------WebKitFormBoundaryrKvJKnAHtuVvEERM
Content-Disposition: form-data; name="Id"

1
------WebKitFormBoundaryrKvJKnAHtuVvEERM
Content-Disposition: form-data; name="Name"

Model1
------WebKitFormBoundaryrKvJKnAHtuVvEERM--

Monday, November 12, 2018

Install MySQL Docker (Windows)

I assume Docker already installed and running.

Pull mysql container

You can specify version (5.7). If version is not given it will download latest version.
C:\>docker pull mysql/mysql-server:5.7
5.7: Pulling from mysql/mysql-server
e64f6e679e1a: Already exists
478c78606b7e: Pull complete
81ab104e859d: Pull complete
d3565df0a804: Pull complete
Digest: sha256:79d65bf4360056b0709b4a1c4996f7ef8265ae6ca67462a8570ac1fa0855758b
Status: Downloaded newer image for mysql/mysql-server:5.7
Check docker image
C:\>docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
mysql/mysql-server         5.7                 76ac6291d3cf        2 weeks ago         234MB
Run mysql instance
docker run --name mysql1 -e MYSQL_USER=root -e MYSQL_PASSWORD=root -e MYSQL_DATABASE=homedb -p 3306:3306 -d mysql/mysql-server:5.7 
Check docker processes
C:\>docker ps
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS                             PORTS                 NAMES
44f6c176bb23        mysql/mysql-server:5.7   "/entrypoint.sh mysq…"   14 seconds ago      Up 13 seconds (health: starting)   3306/tcp, 33060/tcp   mysql1

Connect MySQL on docker

docker exec -it mysql1 mysql -uroot -p
If you did not provide a password in docker run command then system will generate a password. To change password and give some permissions:
C:\>docker logs mysql1 2>&1 | FindStr GENERATED
[Entrypoint] GENERATED ROOT PASSWORD: yBiG5ynmyvVurAw93HDok3buGhi

docker exec -it mysql1 mysql -uroot -p

ALTER USER 'root'@'localhost' IDENTIFIED BY 'root';

CREATE USER 'root'@'%' IDENTIFIED BY 'root';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;

SHOW GRANTS FOR 'root'@'%';

Connect MySQL on client

C:\Program Files\MySQL\MySQL Workbench 8.0 CE>mysql -h localhost -P 3306 -u root -p
mysql> select @@hostname;
+--------------+
| @@hostname   |
+--------------+
| 44f6c176bb23 |
+--------------+
1 row in set (0.00 sec)