WCF unable to locate ConnectionString - c#

Over the last couple of days I've been researching WCF. I've been reading various discussions and following a number of different walkthroughs, most notably the one linked below.
WCF Getting Started Tutorial
I'm now trying to convert these skills into a different scenario. The file structure is exactly the same as what was stated in the aforementioned walkthrough. There is one WCF Service Library, a Host (Console Application) and a Client (Console Application). The host is setup in the same manor as the walkthrough, the client has been altered to allow user input instead of hardcoded values and the WCF code has been provided below.
After a value is provided the WCF Library will run until the following line var userData = repository.GetById(userId);. When the breakpoint is reached and I step over, an exception is thrown stating that the ConnectionString expected doesn't exist. I've tested putting the connection string in the Client and WCF projects but to no avail. I've also ensured EntityFramework and Service.Configuration DLLs are also added as references.
It's possible I am missing another DLL, App.config setting or I've completely messed up and misinterpretted what I can do with a WCF Service Library so I'm looking for some advice on how to rectify the issue in the previous paragraph or a link which helps me understand the problem
IService.cs Code
[ServiceContract(Namespace = "....")]
public interface IUser
{
[OperationContract]
User GetUser(int userId = 0);
}
[DataContract]
public class User
{
[DataMember]
public int UserId { get; set; }
[DataMember]
public string UserName { get; set; }
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
}
Service.cs Code
public class UserService : IUser
{
public User GetUser(int userId = 0)
{
User user = null;
using (var context = new Context())
{
var repository = new Repository(context);
var userData = repository.GetById(userId);
if (userData != null)
{
user = new User
{
UserId = userId,
FirstName = userData.CustomerFirstName,
LastName = userData.CustomerSurname,
UserName = userData.CustomerEmail
};
Console.WriteLine("UserId : {0}", userId);
Console.WriteLine("FirstName : {0}", userData.CustomerFirstName);
Console.WriteLine("LastName : {0}", userData.CustomerSurname);
Console.WriteLine("UserName : {0}", userData.CustomerEmail);
}
}
return user;
}
}
Edit:
<add name="CONTEXT"
connectionString="Server=SERVER;Database=DATABASE;uid=DATABASE;pwd=DATABASE;"
providerName="System.Data.SqlClient" />

Your connection string must be set in the App.config of the executing assembly, not in the assembly directly using it. This means that although your service implementation (Service.cs) is located in your WCF Library assembly, the connection string must be located in the App.config of your host project. If you declare an App.config file into your WCF Library, it will simply be ignored.
The client will not access the database, it will consume your service which is who accesses the database. Therefore, there is no need to declare the connectiong string in the client App.config.

Related

How to utilise Entity Framework with a database hierarchy from API data

I might not have worded this question in the correct format as it's difficult to explain what the problem is. From the research I've gathered I think database hierarchy is something that I'm trying to utilize when using Entity Framework to create a database, I'll try to explain my problem in the best way possible.
Firstly, I'm running a Visual Studio 2019 project with a console application. This is my Program.cs file which is currently using a get request from an API URL with RESTSHARP then performing deserialization.
static void Main(string[] args)
{
getAPIData()
}
public static void getAPIData()
{
var client = new RestClient(URL);
var request = new RestRequest();
var response = client.Execute(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string rawResponse = response.Content;
Requests.Rootobject result = JsonConvert.DeserializeObject<Requests.Rootobject>(rawResponse);
}
}
As you can see above, the raw data that's gathered from the URL (my API) is converted to a JSON format. And when I debug the code, it stores the code perfectly into the Requests DTO, as I'll show below.
public class Requests
{
public int Id { get; set; }
public class Rootobject
{
public Operation operation { get; set; }
}
public class Operation
{
public Result result { get; set; }
public Detail[] details { get; set; }
}
public class Result
{
public string message { get; set; }
public string status { get; set; }
}
public class Detail
{
public string requester { get; set; }
public string workorderid { get; set; }
public string accountname { get; set; }
}
}
The recently converted API data is now stored in this class in this correct format. Which is what's necessary for the API itself since it comes in numerous classes. This object now holds all the relevant data I need, now I can utilize the entity framework to generate an appropriate table that will hold this into an SQL server.
Here is the Entity Framework class.
public class TransitionContext : DbContext
{
private const string connectionString = #"(connection string here)";
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(connectionString);
}
public DbSet<Requests> Requesting { get; set; }
}
Currently, when I run the package manager console commands to build a migration and setup a connection to the server, it works fine (Obviously I've not included my real connection string for privacy reasons). However, when I use the "Update-Database" command from the DbSet which is my DTO for the API data. The only key that is displayed is an ID, nothing else.
SQL requests table
All that's generated here is an Id key from the Requests Dto. Now, on the API itself, there is no ID key, I added it in there because Entity Framework said I had to have an ID key and was displaying errors until I made one. But now that's all it's generating when I "Update-Database".
The reason why I showed as much data as I have done, is because the process is simply exporting the converted JSON data (a recently gathered API) into an SQL table. Or tables so that it supports a hierarchy, anything that will map correctly from the DTO to the database. But as of right now, my only issue with the project is that only an ID is being generated.
So I'm not sure where I'm going wrong here or how to get this working as I intend it to work. Apologies for the really long explanation, I tried to condense it as much as I could, any help would be appreciated and any questions I'm free to answer, thank you!

WCF Test Client error

I am running my WCF service with Entity Framework.
public List<Website> getWebsites()
{
try
{
using (MyInfoEntities ent = new MyInfoEntities())
{
return ent.Websites.ToList();
}
}
catch (Exception e)
{
throw e;
}
}
But when I invoke my service using Visual Studio 2012 I get an error:
Failed to invoke the service.
Possible causes: The service is offline or inaccessible; the client-side configuration does not match the proxy; the existing proxy is invalid. Refer to the stack trace for more detail. You can try to recover by starting a new proxy, restoring to default configuration, or refreshing the service.
As I am totally new to WCF I don't know where to search and what to do.
Your probably not going to be able to return an entity framework object like that directly. Complex objects that are returned from WCF need to be wrapped around a DataContract attribute such as the following:
[DataContract]
public class Website
{
[DataMember]
public long idWebsite{ get; set; }
[DataMember]
public string Name{ get; set; }
[DataMember]
public string MacAddHostess { get; set; }
}

WCF client application hangs

I'm a newbie to WCF technology. My current problem is that my windows forms app isn't getting a respond from wcf program. Here is the code for my windows forms app :
WCFService.PMSService obj = new WCFService.PMSService();
string xx = obj.Test("Hello");
MessageBox.Show(xx);
My windows forms app hangs on this line -> string xx = obj.Test("Hello");
Here is the code for wcf my program :
Interface/Declaration page
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract]
public interface IPMSService
{
[OperationContract]
string DetermineGender(PersonalInfo pInfo);
[OperationContract]
string Test(string val);
}
[DataContract]
public enum Gender
{
[EnumMember]
Male,
[EnumMember]
Female,
[EnumMember]
None
}
// Use a data contract as illustrated in the sample below to add composite types to service operations
[DataContract]
public class PersonalInfo
{
[DataMember]
public string name
{
get { return name; }
set { name = value; }
}
[DataMember]
public string surname
{
get { return surname; }
set { surname = value; }
}
[DataMember]
public string idNo
{
get { return idNo; }
set { idNo = value; }
}
Implementation page
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
public class PMSService : IPMSService
{
public string DetermineGender(PersonalInfo pInfo)
{
Gender Result = Gender.None;
int idNo = Convert.ToInt32(pInfo.idNo.Substring(6, 4));
if (idNo >= 5000)
Result = Gender.Male;
else
Result = Gender.Female;
return Result.ToString();
}
public string Test(string val)
{
return "U passed " + val;
}
}
Does anybody know the possible cause ?
The best suggestion (and perhaps so obvious that many overlook) for someone new to WCF is to become familiar with WCF Tracing and Message Logging. The WCF tracing functionality provides a relatively simple, built-in method to monitor communication to/from WCF services. For test and debugging environments, configure informational or verbose activity tracing and enable message logging. The combination of activity tracing and message logging should prove beneficial when initially deploying and testing new services or adding new operations and/or communication bindings to existing services.
The following links provide a good overview:
http://msdn.microsoft.com/en-us/library/ms733025.aspx
http://msdn.microsoft.com/en-us/library/aa702726.aspx

Convert serialized WCF model back to native model

I have a solution with 3 projects:
Client
Models
WCF Service
The Models project has POCO classes that reference my database table like below:
[DataContract]
[Table("users")]
public class User
{
public User()
{
}
[DataMember]
[Key, Column("userid", TypeName = "int")]
public Int32 UserId { get; set; }
[DataMember]
[Column("username", TypeName = "varchar")]
public String UserName { get; set; }
The WCF Service Project has a reference to Models in order to return the Model from a Method like below:
public User ValidateUser(string organization, string userName, string password)
{
Model.Poco.User user = new Model.Poco.User();
user.UserId = 1;
user.BoardMember = true;
user.Email = "test#yahoo.com";
user.FirstTimeLogin = false;
user.IsActive = true;
user.Notes = "notes";
user.Password = "xxxxxx";
user.UserName = "user1";
return user;
}
Now, my client has a Service Reference to the WCF Service and the code to call it is like below:
private void button1_Click(object sender, EventArgs e)
{
WCFService.Service1Client client = new WCFService.Service1Client();
var user = client.ValidateUser("test", "test", "test");
}
It's working ok like this, If I navigate "user" variable It has all the object properties from the WCF Service, but what I want to do is to have:
Model.Poco.User user = client.ValidateUser("test", "test", "test");
But if I do this Im getting an error that its not possible to convert from: WCFService.User to Model.Poco.User.
Any clue on how can I convert the serialized object to the native one. Note, that Im using the same object on both client and WCF Service because Im referencing the *Models project on both.*
Appreciate any help in advance!!
When you generate the service reference in the client project, check the option to reuse types in referenced assemblies. Otherwise the tool will generate new classes based on the WSDL as part of the service reference.

change the connection string values the app.config

I am trying to change the connection String values
connectionString="Data Source=localhost;Initial Catalog=Tracker;Persist Security Info=false;User ID=sa;Password=p#ssw0rd"
from my user interface. Could any one help to change the settings from the user interface in the windows application?
From the comment thread on the original post, it sounds like the OP needs to enumerate data sources and allow a user to pick one (and perhaps store that preference). Assuming that is the case...
The actual connection to the database should be secured using integrated Windows security if at all possible. This a best practice. Integrated security eliminates the need to store credentials anywhere.
If the goal is to pick a datasource, it's not hard to list all databases within an environment using C#.
The user's preference/selection should be stored somewhere other than the app.config. The registry, isolated storage, or an XML file are all valid options if no credentials are involved.
ASP.NET provides the Web Site Administration Tool to view and manage the configuration settings for your ASP.NET website. These configuration settings are stored in an xml file called web.config.
web.config is an application configuration file used to define configuration settings such as connecting strings, authentication, authorization etc., for an ASP.NET application
The tool provides an easy to use interface to edit the configuration settings. However this tool works well when you have to manually make changes. At times, there could be a possibility where we need to make changes to the web.config at runtime. For example: a user requesting to control the connecting string, change session timeouts and so on.
For this purpose, ASP.NET provides the Configuration API to programmatically manipulate the configuration settings in web.config. The API’s are contained in the System.Configuration and System.Web.Configuration namespaces. In fact, internally the Web Site Administration Tool uses the same API to edit configuration settings.
The WebConfigurationManager class in the System.Web.Configuration namespace is used to create a Configuration object. This object is used to read and write changes to the web.config file. See.
See also Securing Connection Strings
Let me clarify that this is not what you're asking but by reading this, you will be able to find some clues and come to know what is recommended and what is not.
If this is a Windows application then you don't need to change the app.config file to change the active database connection. I've written about this on my blog.
User below method to change connection string using C# :
public void SaveConnectionString(DbInfo dbinfo, string path,string appConfigFile)
{
try
{
string configFile = Path.Combine(path, appConfigFile);
var doc = new XmlDocument();
doc.Load(configFile);
XmlNodeList endpoints = doc.GetElementsByTagName("connectionStrings");
foreach (XmlNode item in endpoints)
{
if (item.HasChildNodes)
{
foreach (var c in item.ChildNodes)
{
if (((XmlNode)c).NodeType == XmlNodeType.Element)
{
var adressAttribute = ((XmlNode)c).Attributes["name"];
if (adressAttribute.Value.Contains("YourConStrName"))
{
if (dbinfo.dbType == dataBaseType.Embedded)
{
((XmlNode)c).Attributes["connectionString"].Value = SetupConstants.DbEmbededConnectionString;
((XmlNode)c).Attributes["providerName"].Value = SetupConstants.DbEmbededConnectionProvider;
}
else if (dbinfo.dbType == dataBaseType.Microsoft_SQL_Server)
{
if (dbinfo.sqlServerAuthType == SqlServerAuthenticationType.SQL_Server_Authentication)
{
// ((XmlNode)c).Attributes["connectionString"].Value = string.Format(SetupConstants.dbConnStringwithDb, dbinfo.databaseAdress, SetupConstants.SqlDbName, dbinfo.userId, dbinfo.password) + "MultipleActiveResultSets=true;";
((XmlNode)c).Attributes["connectionString"].Value = string.Format(SetupConstants.dbConnStringwithDb, dbinfo.databaseAdress, dbinfo.DatabaseName, dbinfo.userId, dbinfo.password) + "MultipleActiveResultSets=true;";
}
else if (dbinfo.sqlServerAuthType == SqlServerAuthenticationType.Windows_Authentication)
{
//((XmlNode)c).Attributes["connectionString"].Value = string.Format("Data Source={0};Initial Catalog={1};Integrated Security=True;MultipleActiveResultSets=true;", dbinfo.databaseAdress, SetupConstants.SqlDbName);
((XmlNode)c).Attributes["connectionString"].Value = string.Format("Data Source={0};Initial Catalog={1};Integrated Security=True;MultipleActiveResultSets=true;", dbinfo.databaseAdress, dbinfo.DatabaseName);
}
((XmlNode)c).Attributes["providerName"].Value = SetupConstants.DbSqlConnectionProvider;
}
}
}
}
}
}
doc.Save(configFile);
string exePath = Path.Combine(path, "EDC.Service.exe");
InstallerHelper.EncryptConnectionString(true, exePath);
}
catch (Exception ex)
{
//TODO://log here exception
Helper.WriteLog(ex.Message + "\n" + ex.StackTrace);
throw;
}
}
Add bellow class DBinfo
public class DbInfo
{
public DataBaseType dbType { get; set; }
public SqlServerAuthenticationType sqlServerAuthType { get; set; }
public string ConnectionString { get; set; }
public string databaseAdress { get; set; }
public string userId { get; set; }
public string password { get; set; }
public string Port { get; set; }
public string DatabaseName { get; set; }
}
public enum DataBaseType
{
Unknown = 0,
Embedded = 1,
Microsoft_SQL_Server =2,
}
public enum SqlServerAuthenticationType
{
Windows_Authentication = 0 ,
SQL_Server_Authentication =1
}

Categories

Resources