I want to create a test WCF service like this: http://www.mywebsite.com/admin/Service1.svc
I create a new project -> WCF -> WCF Service Application
I wrap the automatically created Service1.svc and IService1.vb in "Namespace Admin" like this:
Namespace Admin
Public Class Service1
Implements IService1
Public Sub New()
End Sub
Public Function GetData(ByVal value As Integer) As String Implements ...
Return String.Format("You entered: {0}", value)
End Function
' deleted rest of class
End Class
End Namespace
But when I try to add a service reference to Service1.svc, I get this error:
There was an error downloading
'http://localhost:51826/Service1.svc/_vti_bin/ListData.svc/$metadata'.
If I remove my "Namespace Admin" and put Service1.svc into an "Admin" folder, then it works perfectly, but I need to structure my code since this is going to be a large project.
How can I use "Namespace" without it failing?
When you create a "WCF 4.0 Service Application", it uses the Convention-over-Configuration strategy to configure your web service; One of these conventions is that the implementation of the service is placed inside the "Default Assembly Namespace". To fix this; follow these steps:
Right-click on the .svc file and choose View Markup. This is the XML file that binds the .svc file to the implementation of your service
Change the "Service" attribute value to match the correct location of the service implementation like WcfService1.Admin.Service1
Build the assembly.
Test the service.
Namespaces and folders are unrelated. You can have any namespace and put the svc in any folder you desire.
VB provides an implicit root namespace which is your project's name by default. You can see it Project > Properties > Application tab.
Nevertheless, since you want to add a "Admin" namespace, now your class is under second level namespace - <yourProjectName>.Admin.
This has to reflect in your svc file - you have to add "Admin" to the service attribute.
Right click on your svc file in the project and choose > Show markup. Make the change to Service attribute of the ServiceHost tag.
<%# ServiceHost Language="VB" Debug="true" Service="<YourProjectName>.Admin.Service1" CodeBehind="Service1.svc.vb" %>
Related
I have .net core standard class library which is essentially a DAL with several class methods that return collections and objects from a database. The connection string is in the appsettings.json file of the ASP.net 2 core web app. I also want to access this class library from a console app project where the configuration file with the connection string will be present in that console app project.
This was simple in .net prior to .net core. The DAL class library would just access the web.config from a web project and an app.config from a console application as it the library is referenced in both the web app and console apps. But it doesn't seem like this is at all possible.
I'm looking for the simple solution in .net core to get a connection string from web app or console app as the case may be.
Where you're probably going wrong is that you want to access configuration from your class library, but then you want to leak details specifically about the caller (That it will have a web.config).
But what if you decide in your Web Application you want to use Azure Key Vault or another secrets mechanism? Does your class library need to then change it's entire implementation to use Key Vault? And then does that mean your console application also has no option but to use Key Vault too?
So the solution is to use dependency inversion. Put simply, let's say I have code like the following :
interface IMyRepositoryConfiguration
{
string ConnectionString {get;}
}
class MyRepositoryConfiguration : IMyRepositoryConfiguration
{
public string ConnectionString {get;set;}
}
class MyRepository
{
private readonly IMyRepositoryConfiguration _myRepositoryConfiguration;
public MyRepository(IMyRepositoryConfiguration myRepositoryConfiguration)
{
_myRepositoryConfiguration = myRepositoryConfiguration;
}
}
Now in my startup.cs I can do something like :
services.AddSingleton<IMyRepositoryConfiguration>(new MyRepositoryConfiguration {//Set connection string from app settings etc});
And now my class library doesn't need to know exactly how those configuration strings are stored or how they are fetched. Just that if I request an instance of IMyRepositoryConfiguration, that it will have the value in there.
Alternatively of course, you can use the Options class too, but personally I prefer POCOs. More info here : https://dotnetcoretutorials.com/2016/12/26/custom-configuration-sections-asp-net-core/
It is very much possible to access "connection strings" or other configuration data easily in .Net core without much additional effort.
Just that the configuration system has evolved (into something much better) & we have to make allowances for this as well (& follow recommended practices).
In your case as you are accessing the connection string value in a standard library (intended to be reused), you should not make assumptions as how the configuration values will be "fed" to your class. What this means is you should not write code to read a connection string directly from a config file - instead rely on the dependency injection mechanism to provide you with the required configuration - regardless of how it has been made available to your app.
One way to do this is to "require" an IConfiguration object to be injected into your class constructor & then use the GetValue method to retrieve the value for the appropriate key, like so:
public class IndexModel : PageModel
{
public IndexModel(IConfiguration config)
{
_config = config;
}
public int NumberConfig { get; private set; }
public void OnGet()
{
NumberConfig = _config.GetValue<int>("NumberKey", 99);
}
}
In .net core, before the app is configured and started, a "host" is configured and launched. The host is responsible for app startup and lifetime management. Both the app and the host are configured using various "configuration providers". Host configuration key-value pairs become part of the app's global configuration.
Configuration sources are read in the order that their configuration providers are specified at startup.
.Net core supports various "providers". Read this article for complete information on this topic.
I have a WCF Service hosted in IIS. This solution is composed of 2 projects: Service and Data. Service depends on Data, like so:
Service -> Data
I've been trying to invert the dependency, like so:
Service <- Data
Which is quite a headache using WCF, since the WCF service constructor must be parameter-less (by default).
I hear it's possible to inject the dependency using Ninject and its WCF extension, so I tried to integrate it to my solution, but it's still not clear to me in which project should be the related files and references? What I did is :
Download Ninject using NuGet
Add Ninject to both my Data and Service projects (that created the NinjectWebCommon file in the App_Start folder of the Service Project
Create a IDataProxy interface in my Service project
Implement the interface in my Data project
Add a IDataProxy argument to the WCF service constructor
Added the factory configuration in the .svc file markup
Up to that point, I'm pretty sure I'm doing it right. Now the shaky part :
I created a DataInjectionModule in my data project with this code :
namespace Data
{
public class DataInjectionModule : NinjectModule
{
public override void Load()
{
Bind<IResolutionRoot>().ToConstant(Kernel);
Bind<ServiceHost>().To<NinjectServiceHost>();
Bind<IDataProxy>().To<DataProxy>();
}
}
}
I finally tried to register the service in the NinjectWebCommon files (of both projects to be sure) like that :
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IService>().To<Service>()
.WithConstructorArgument("IDataProxy", context => context.Kernel.Get<IDataProxy>());
}
When I try to start my service, I still get this :
The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor. To fix the problem, add a default constructor to the type, or pass an instance of the type to the host.
I have a feeling that the problem resides in the fact that I did not bind my DataInjectionModule in the kernel, but if I try to do so, I must add a dependency from Service to Data, which is what I'm trying to avoid.
General expert advice would be greatly appreciated. Thanks.
Please check your point 6: "Added the factory configuration in the .svc file markup."
Have you done it properly?
The *.svc file should have this code:
Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory"
I'm running on a windows 2008 server. I have one Web service which calls a wcf service.
Within the WCF service it attempts to cast a date 20/08/2010 which fails because it thinks it in US format not Austrlaian.
So far I have:
On control panel change the region to English Australian under format
Under the Administrative tab I have also set system local to English (Austrlian)
within IIS7 at the default web site level I have changed Culture and UI culture under the .Net globalization.
I've also done this at the Web service and WCF Nodes
I have added the following to the Web service and WCF apps web.config file
<globalization requestEncoding="utf-8"
responseEncoding="utf-8"
culture="en-AU"
uiCulture="en-AU" />
This finally changed the culture in the Web service but the WCF service remains US culture.
Can anyone tell me what else I can try?
The WCF will ignore your globalization configuration if you do not set aspNet compatibility:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
...
To use that mode your service class must have the attribute AspNetCompatibilityRequirements set to Allowed or Required:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ServiceClass
{
...
}
This could work if you want to apply the Culture and CultureUI from config file.
Or you could either try to force the Culture in your WCF service code, if you are sure that it will not change dynamically. For instance, in your service class constructor. Note that this is not a best practice, perhaps you should use a Context initializer, but this one is quite simple.
public ServiceClass()
{
...
System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-AU");
System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-AU");
}
More info:
setting-cultureinfo-on-wcf-service-calls
using-call-context-initializers-for-culture
The problem is in the culture that is set for a user used in the application pool.
I found the following way to resolve this issue:
If the application pools uses ApplicationPoolIdentity change it to NETWORKSERVICE (unfortunatly I didn't found how to set regional settings for ApplicationPoolIdentity)
Set regional settings you need (en-AU) on the current user and than copy them for the system accounts as described here.
You can do it in the Global.asax.cs file, in the Application_Start file:
using System.Threading;
using System.Globalization;
public class Global : HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("en-AU");
}
}
I'm trying to have my WCF services run completely off HTTPS. However when WCF generates the WSDL it provides locations that are not secure (http) and not allowed (rejected) by server.
How do i get this:
<wsdl:import namespace="https://www.mydomain.com/ogc/csw/ebrim/wsdl1.1" location="http://www.mydomain.com/ogc/csw?wsdl=wsdl0"/>
to read this (notice location attribute now using https):
<wsdl:import namespace="https://www.mydomain.com/ogc/csw/ebrim/wsdl1.1" location="https://www.mydomain.com/ogc/csw?wsdl=wsdl0"/>
I can specify my namespace in my interface file but i don't' see how to specify location.:
[System.ServiceModel.ServiceContractAttribute(Namespace = "https://www.mydomain.com/ogc/csw/ebrim/wsdl1.1", ConfigurationName = "MyDomain")]
public interface ICatalog
{
I've tried modifying my baseAddress, but that didn't do anything.
You have to specify the httpsGetEnabled configuration property on the wcf stack. Check the following link to the MSDN
I am trying to test a class in Service handler using NUnit project.
My service handler class is part of a class library project which gets data from a WCF service.
When call from test project method comes into service handler class and a method in that class tries to creat clients object with statement - using (Client client = new Client()), it throws exception :
"Could not find default endpoint element that references contract 'XYZ' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element."
Loos like my app.config file is not being read in this case, thats why this exception is coming. has anybody ever faced this issue? I need urgent help regarding this.
Add an App.Config to your NUnit assembly.
Add the WCF service client config to the App.Config and it should work.
Rename app.config to the namespace of the Nunit Assembly that contains your tests, for example;
Namespace.Project.Class.config
namespace Namespace.Project.Class
{
[TestFixture]
public class Imports
{
[Test]
public void InsertFile()
{
}
}
}