After getting input in another thread here on the forum [StackOverFlow][1]
[1]: Getting a nullreference when passing a complex object from KSOAP2 to WCF have i reached conclusion that my problem is with the WCF service itself. It seems that the service is not able to understand the object that it's receiving.
No matter what I do the object passed is always null.
I have even tried declaring the datamember explicit even though it should not be necessary in the current version of WCF.
Here's the class I'm trying to pass through the WCF:
namespace ModelLayer
{
[DataContract]
public class User
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string UserName { get; set; }
[DataMember]
public string Mac { get; set; }
public User()
{
}
}
}
My service interface:
[ServiceContract (Namespace = "http://nordahl.org/")]
public interface IWcfFoodAndAllergi
{
[OperationContract]
int InsertUser(User _user);
[OperationContract]
User GetUser(string _mac);
[OperationContract]
int InsertRecipe(Recipe _recipe);
[OperationContract]
List<Recipe> GetRecipeByAllergi(List<Allergies> _allergies);
[OperationContract]
List<Recipe> GetRecipeByType(string _type);
[OperationContract]
List<Recipe> GetRecipeByName(string _name);
}
}
And lastly the webconfig file itself:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" maxRequestLength="1048576"/>
</system.web>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="1073741824" />
<fileExtensions allowUnlisted="true">
<remove fileExtension=".cs"/>
<add fileExtension=".cs" allowed="true"/>
</fileExtensions>
</requestFiltering>
</security>
</system.webServer>
<system.serviceModel>
<services>
<service name="WcfFoodAndAllergi.WcfFoodAndAllergi">
<!-- Use a bindingNamespace to eliminate tempuri.org -->
<endpoint address=""
binding ="basicHttpBinding"
bindingNamespace="http://nordahl.org/"
contract="WcfFoodAndAllergi.IWcfFoodAndAllergi"
/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name ="">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
I had a similar problem to yours when a complex object referenced another complex object in a T4 generated class. If you are using an include in an obtain method, or another method relating to Entity or objects linking complex objects to each other; you may get a circular reference error. I had a friend show me how to fix this with a custom class that sets up an attribute:
Complex Object won't return when using 'include' syntax in WCF with Entity Version 6
Related
I am new here. I want create a WCF WebService using Visual Studio and use it in Xamarin Forms application. This is my ultimate goal. Now I created WCF Service project and starts IIS service on my Mac machine(Windows 8 OS). But When I run the code already given in project to check whether things are alright or not, I am getting following error :
Failed to add a service. Service metadata may not be accessible. Make
sure your service is running and exposing metadata.
My Web.config file is as below :
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5.2"/>
<httpRuntime targetFramework="4.5.2"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
Service.svc file :
<%# ServiceHost Language="C#" Debug="true" Service="Service" CodeBehind="~/App_Code/Service.cs" %>
Service.cs file :
public class Service : IService
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
I am working on wcf first time so created just sinple wcf ,problem is when i run service from visual studio its working fine but when i deploy it on iis it giving HTTTP 500 Error
my web config file is as below
<?xml version="1.0"?>
<configuration>
<appSettings/>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<httpRuntime/>
<pages controlRenderingCompatibilityVersion="4.0"/>
</system.web>
<system.serviceModel>
<services>
<service name="WcfService2.Service1" behaviorConfiguration="servicebehavior">
<endpoint address="" binding="webHttpBinding" contract="WcfService2.IService1" behaviorConfiguration="web"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="servicebehavior">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
and svc file is as below
namespace WcfService2
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
// NOTE: In order to launch WCF Test Client for testing this service, please select Service1.svc or Service1.svc.cs at the Solution Explorer and start debugging.
public class Service1 : IService1
{
public string JSONData(string id)
{
return "you requested prduct" + id ;
}
public void DoWork()
{
}
}
}
and interface is as below
namespace WcfService2
{
// 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 IService1
{
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "/json/{id}")]
string JSONData(string id);
void DoWork();
}
}
https://stackoverflow.com/a/11460220/2211593
my iis server was not having feature of HTTP activation enabled so after lot of googling i found this solution. very useful for me i spent almost half of day to find the solution of this small issue
Car.cs
[DataContract]
public class Car
{
[DataMember]
public string Id { get; set; }
[DataMember]
public Bitmap Image { get; set; }
}
ICarService.cs
[ServiceContract]
public interface ICarService
{
[OperationContract]
[WebGet(UriTemplate = "Car/{id}")]
Car GetCarId(string id);
}
CarService.svc.cs
public class CarService : ICarService
{
public Car GetCarId(string id)
{
var newCar = new Car
{
Id = id,
Image = new Bitmap("../../Atish.jpg")
};
return newCar;
}
}
web.config
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<services>
<service name="CarHaat.CarService">
<endpoint address="" behaviorConfiguration="restfulBehavior"
binding="webHttpBinding" bindingConfiguration="" contract="CarHaat.ICarService" />
<host>
<baseAddresses>
<add baseAddress="http://localhost/bookservice" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="restfulBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
Problem is .... when i hit this url localhost:4765/CarService.svc/car/1 in browser, I get following exception. How can i resolve it?? I want to return an image in json format.
what is the call stack trace? if I were you, I would go to the debug > Exception menu and then tick the "thrown" check box for the Common Language Runtime Exceptions item. This will then take you to exactly where the exception is being thrown from. To me, I believe it could be thrown from the Bitmap constructor as you are giving it an incorrect path. you need to map the path to the image file in question by using Server.MapPath for example. It needs a fully qualified path to the file in question when it comes to the web platform.
in addition to that, the file will be locked until you dispose of the bitmap object so you may have issues. The best thing to do is probably return the byte[] of the image file to the client and let the client side deal with streaming it to the page (for example using the response to write the bytes to the page). it also makes sense if you are using the WCF platform and making a form of an API system, where you are not tied to using the .NET BCL's but to make it as generic as possible that majority of not all of the clients understand the native types
Return the image Serialized in Base64 (string) and then in the client Deserialize it
Like this
//Serialize
var bytes = File.ReadAllBytes(#"bbbd996028159395cce9b63d717bf0ef.jpeg");
var base64 = Convert.ToBase64String(bytes);
//Deserialize
var nbytes = Convert.FromBase64String(base64);
File.WriteAllBytes(#"yayaya.jpeg", nbytes);
Was trying alot and brows-ing around but I fail to figure out what is wrong with my WCF service.
What I am trying to acchive:
I am builindg a WCF that would expose some data as a json structure over HTTP
I will evenutally use that in an andorid app to show the data.
The mockup:
1.) The interface:
namespace WcfSyncDBService
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "ISyncDBService" in both code and config file together.
[ServiceContract]
public interface ISyncDBService
{
[OperationContract]
[WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Wrapped,
ResponseFormat = WebMessageFormat.Json, UriTemplate = "GetTodoItems")]
TodoItem[] GetTodoItems();
}
[DataContract(Name = "TodoItems")]
public class TodoItem
{
[DataMember(Name = "Id")]
public int Id { get; set;}
[DataMember(Name = "Category")]
public string Category { get; set; }
[DataMember(Name = "Summary")]
public string Summary { get; set; }
[DataMember(Name = "Description")]
public string Description { get; set; }
}
}
2.) The Service:
namespace WcfSyncDBService
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "SyncDBService" in code, svc and config file together.
public class SyncDBService : ISyncDBService
{
public TodoItem[] GetTodoItems()
{
var context = new SyncDBEntities();
var query = from i in context.todo select i;
var itemList = query.ToList();
List<TodoItem> todoList = new List<TodoItem>();
foreach (var item in itemList)
{
TodoItem i = new TodoItem
{
Id = item.C_id,
Category = item.category,
Summary = item.summary,
Description = item.description
};
todoList.Add(i);
}
return todoList.ToArray();
}
}
}
3.) Web config:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="WcfSyncDBService.SyncDBService">
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address="" binding="webHttpBinding" contract="WcfSyncDBService.ISyncDBService" behaviorConfiguration="web" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<connectionStrings>
<add name="SyncDBEntities" connectionString="metadata=res://*/SyncDBmodel.csdl|res://*/SyncDBmodel.ssdl|res://*/SyncDBmodel.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=SyncDB;integrated security=True;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>
When I run the service I get the definition and the wsdl:
http://localhost:18131/SyncDBService.svc
But when I try to call the function http://localhost:18131/SyncDBService.svc/GetTodoItems/ I get an error "Endpoint not found."
I know the error is probably in the web.config but I simply fail to find it hope someone can help me out.
EDIT1: (web.config after Siva's sugesstion)
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="WcfSyncDBService.SyncDBService">
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address="" binding="webHttpBinding" contract="WcfSyncDBService.ISyncDBService" behaviorConfiguration="web" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true">
<serviceActivations>
<add relativeAddress="SyncDBService.svc" service="WcfSyncDBService.SyncDBService" />
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<connectionStrings>
<add name="SyncDBEntities" connectionString="metadata=res://*/SyncDBmodel.csdl|res://*/SyncDBmodel.ssdl|res://*/SyncDBmodel.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=SyncDB;integrated security=True;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>
You need to configure relative address on service host,
<serviceHostingEnvironment multipleSiteBindingsEnabled="true">
<serviceActivations>
<add relativeAddress="SyncDBService.svc" service="WcfSyncDBService.SyncDBService" />
</serviceActivations>
</serviceHostingEnvironment>
I have used VS2012 to create a new WCF website (Add->New Web Site->WCF Service).
'Out of the box' this gives me the following web.config file:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5"/>
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
It also gives me an initial Service class as follows:
public class Service : IService
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
I then F5 to start the project and it fires up a browser window listing the dir contents, including Service.svc.
I want to type in a URL to call the GetData method. What do I type into the browser address bar, and how to I configure and/or decorate the service so I can type a URL into the browser and see a JSON format string being returned?
Mark the Operation in your contract (IService interface) with following attribute - [WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, UriTemplate="GetData/{id}")]
And then try invoking your service from browser by adding GetData/[any number]