XML put constant settings in App.config file - xamarin

I have a class called Constants.cs that contains app settings. I want to add an App.config file and put the settings from Constants.cs to App.config file in order to be able to run my application in different environments with same settings.
If my constants.cs class looks like this:
public class Constants
{
public static string LoginSubmitText => "Submit";
public static string LoginBackBtnText => "Back";
public static string SettingsPageTitleSize => "25";
}
Should then the App.config file look like this?
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key ="LoginSubmitText" value="Submit"/>
<add key ="LoginBackBtnText " value="Back"/>
<add key ="SettingsPageTitleSize" value="25"/>
</appSettings>
</configuration>
And in that case, must I put this App.config file in all three environments, .Android, .IOS and UWP?
Thanks in advance!

You don't have to have App.config in all three platfroms. You can add this class to project with shared code.
I just finished working on similar issue. This is described here in this article. They don't use App.config file and if you insist on having App.config you can write your own implementation of parsing App.config to AppSettings object. I am talking about the method LoadAppSettings. The last part of this method converts json file appsettings.debug.json to AppSettings obejct.
In my case I needed to inject different connection strings regarding to build configuration in my azure pipelines. I use the powershell script to edit appsettings.[build configuration].json file and that solves my issue.

Related

Strange behavior when overriding properties for a spring-boot application deployed as a WAR in a Tomcat

I have a spring-boot application which I need to deploy as a WAR in a tomcat.
I also need to define / override some properties so that this application can work in this environment.
I was able to do so by creating a file tomcat/conf/Catalina/localhost/backend.xml with the same name as my WAR file. Here the content:
<?xml version="1.0" encoding="UTF-8"?>
<Context reloadable="true" crossContext="true" override="true" path="/back" docBase="/home/myAppUser/webapps/backend.war">
<Environment name="spring.profiles.active" value="prod" type="java.lang.String" />
<Environment name="application.attachmentBaseDirectory" value="/home/myAppUser/attachments" type="java.lang.String" />
<Environment name="application.redirect-url" value="http://myapp.mycompany.org/frontend" type="java.lang.String" />
</Context>
All environment variables but application.attachmentBaseDirectory work.
The application continue to use the one defined for my development environment on Windows: C:\tmp\attachments…
Yet, if I create a file /home/myAppUser/application.yml or /home/myAppUser/config/application.yml, the value is correctly overridden…
application:
attachmentBaseDirectory: /home/myAppUser/attachments
But if I define all the values inside this file in place of backend.xml, none of them but application.attachmentBaseDirectory work…
So here is my questions:
Why the overriding in tomcat/conf/Catalina/localhost/backend.xml isn't working for this value, but work for others?
How come the WAR is able to find the application.yml when running inside of a tomcat?
Why the application.attachmentBaseDirectory property does work from the application.yml file, but others don't?
Some more information:
Here the content on my ApplicationProperties.java.
#Component
#ConfigurationProperties("application")
public class ApplicationProperties {
/**
* The URL to which we should redirect the user once he is logged in the application.
*/
private String redirectUrl;
/**
* The base directory in which we should put the attachments.
*/
private String attachmentBaseDirectory;
}
This bean is then use in a #Controller for the redirectUrl to redirect to another web page, and in a #Service for the attachmentBaseDirectory to save files.
I finally found why the property application.attachmentBaseDirectory didn't work when set in tomcat/conf/Catalina/localhost/backend.xml:
It is because it was named application.attachmentBaseDirectory (camel case) and not application.attachment-base-directory (kebab case).
Spring-boot allow relaxed binding, but it seems that to be used through tomcat context, the kebab case way is the one to go.
Yet to solve:
How come the WAR is able to find the application.yml in the home directory when running inside tomcat?
I am suspecting that it is because I launch the tomcat from my home directory.
Why the application.attachmentBaseDirectory works from application.yml but others properties don't?

Best practice for configuration file in Visual studio F# solution

I wonder if there is a best practice for seting up a configuration file in a F# solution.
Below is a sample of my configuration file, which is used by different projects in my F# solution.
myConfig.xml :
<?xml version="1.0" encoding="utf-8" ?>
<Config>
<Segment>
<SegmentTypes>
<Did>did</Did>
<PostCode>postcode</PostCode>
<Ip>/ip</Ip>
</SegmentTypes>
</Segment>
<SThreeConfig>
<AccessKey>aaa</AccessKey>
<SecretKey>bb</SecretKey>
</SThreeConfig>
</Config>
I could put the contain of the above in the built in App.config. As App.config does not allow nested
tags, it will become messy as my configuration grows.
So far the best solution we have found is the following.
Create a top level project configuration, and in that project,
create a source file to read myConfig.xml using xml type provider.
Then wrap the values in myConfig.xml in static properties of
a class AppConfigObj. The other projects in the solution will access configuration properties
via appConfObj.
module Configuration=
open FSharp.Data
open System
// Other projects acccess the configuration properties using AppConfigObj.
type AppConfigObj() =
static let [<Literal>] configXmlFile = "myConfig.xml"
static let config = XmlProvider<configXmlFile>.Load(configXmlFile.ToString())
static member didPath = config.Segment.SegmentTypes.Did
static member postcodePath = config.Segment.SegmentTypes.PostCode
static member ipPath = config.Segment.SegmentTypes.Ip
static member s3AccessKey = config.SThreeConfig.AccessKey
static member s3SecreteKey=config.SThreeConfig.SecretKey
Although the default configuration mechanism is enough, there exists a very practical alternative which is using a config tailored type provider: FSharp.Configuration
This way you work with typed classes for config and setting files.

ConnectionString Exception After Installing WebService

I have a webservice that I am using to get information from users. Before installing the service, it works fine. After installing the service, I am getting an exception "Object reference not set to an instance of an object." The WCF is referencing a dll where validating and writing to the database and return the results. The dll library has an app config where I added the connection string
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<clear/>
<add name="reqInformation" connectionString="Data Source=databasesourceInitial Catalog=databasename;Persist Security Info=True;User ID=username;password=password" providerName="System.Data.SqlClient"/>
</connectionStrings>
</configuration>
I have this class that is getting the connection string
public abstract class BASEClass
{
public static string GetConnectionString
{
get
{
return ConfigurationManager.ConnectionStrings["reqInformation"].ConnectionString;
}
}
}
I added the same connection string to the wcf config file.
In addition, I added a test project to test the service before installing it, it worked fine. I installed the WCF Service and ran the test project again, and it failed. The exception was Object reference not set to an instance of an object.
What am I doing wrong here?
The app config was added to the service Library; however, the service library was not the executing assembly. As a result, it was giving that exception. I moved the connection string int he executing assembly, recompile the code, re-install the service, and test it. All things are working as expected.

Code First entity framework connection string

I have 3 class projects in my solutions.
1. MVC4 project
2. Domain
3. Tests
In the MVC4 project I have added a web.config file with the connection string as
<add name="EfDbContext" connectionString="Data Source=.;Initial Catalog=SportsStore;Integrated Security=true;" providerName="System.Data.SqlClient"/>
I have a class by name EfDbContext in Domain project which inherits DbContext.
When I view the website in browser, I get the server not found error.
I debugged the EfDbContext class and found that the Database.Connection.ConnectionString
is set to \SqlExpress with database as EfDbContext.
Why is that?
You must have your connect string as the FULL namespace to your context when your context class is in a different project
For example:
<add name="YourClassProject.EfDbContext" connectionString="Data Source=.;Initial Catalog=SportsStore;Integrated Security=true;" providerName="System.Data.SqlClient"/>
You should create your DbContext with your connection string name passing to the constructor
public class UnicornsContext : DbContext
{
public UnicornsContext()
: base("EfDbContext")
{
}
}
http://blogs.msdn.com/b/adonet/archive/2011/01/27/using-dbcontext-in-ef-feature-ctp5-part-2-connections-and-models.aspx
Finally, I realized that I added the connection entry in the web.config file created by VS in Views folder.
My bad.

How to merge the applicationSettings of a class library into the host executable's config file

I am reading articles, forum posts about applicationSettings for almost a week now.
In almost every thread there was someone that appears to have correctly pointed out that the class libraries cannot have config files when deployed and their applicationSettings configured at design must be specified/merged in the executable.exe.config configuration file of the application that host/consumes the dll.
Not necessarily true.
You can but you don't need to merge them class library settings unless you want to provide the user with a way to "overwrite" the default values - the ones that are specified using the DefaultValueAttribute hard coded in the assembly.
So, for a very simple, practical example. Let's use VB.NET
1. I created a Class Library project called ClassLibrary.
2. Showing all files, expand MyProject, double click Settings.settings.
3. Adding a setting called Message, application scoped whose value is "Hello!".
4. Create a property in Class1.vb (the automatically added class)
Public Class Class1
Public Shared ReadOnly Property Message As String
Get
Return My.Settings.Message
End Get
End Property
End Class
Create a VB WinForms project and call it WinForm.
Add a reference to the ClassLibrary project.
Add a button to the already created Form1 and double click on it.
8 Add the some code to the the Button1_Click handler. Should look like this.
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
MessageBox.Show(ClassLibrary.Class1.Message)
End Sub
End Class
Have WinForm "Set as Startup project"
Now, while in the IDE everything works beautifully. Run the solution and you'll get the expected Hello! when you press the button. If you go and change the setting in the app.config of the library to say "Good bye!" and you run the solution again you get a "Good bye!"
However, right click on the WinForm project and "Open in Explorer" and get to the Debug folder. There's no WinForm.exe.config file yet. Let's create one quickly.
Switch back to VS and while the WinForm project is selected click to Show All Files.
Expand MyProject, open Settings.settings, create a setting (doens't matter what) and save.
There we go, an App.config was created and if I build this solution, the Debug folder will contain a WinForm.exe.config.
Tell me how I merge my Message setting from the class library config
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="ClassLibrary.My.MySettings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<ClassLibrary.My.MySettings>
<setting name="Message" serializeAs="String">
<value>Hello!</value>
</setting>
</ClassLibrary.My.MySettings>
</applicationSettings>
</configuration>
into the WinForm's config
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="WinForm.My.MySettings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client" />
</startup>
<applicationSettings>
<WinForm.My.MySettings>
<!--<setting name="A" serializeAs="String">
<value>A</value>
</setting>-->
</WinForm.My.MySettings>
</applicationSettings>
</configuration>
so I can change the Message setting's value in the WinForm.exe.config to something else and the application will display this new value overriding the DefaultValueAttribute.
I have done some research lately for this applicationSettings problem.
I found two relatively convenient ways of doing what I was asking for.
I put my thoughts about it together and wrote a blog entry here.
assemblies that your main assembly depend on can and will use settings you define in their individual projects but only during development just because they are build on the fly and contain whatever values you set last time. However when you deploy and think that you can place .config for each assembly they won't work if you expect to change a setting's value and have that reflected at runtime, that's because the last values are set as default values and are hardcoded in.
So you have to either move all your settings to the appSettings in the .config file of the main assembly and inject them at runtime as needed to the assemblies needing them (passing them as arguments).
Otherwise let's say these are your config files while in development:
2
3
For deployment you will have to create a configuration section in the main config file and point to
your modified "ClassLibrary.dll.config":
You don't have to point to external files though, the config sections declarations can point to their definitions further down in the main config file like this.

Resources