how to call WCF service method from Angular js - c#

I created a WCF service and I am not able to call any method from my angular js script.
namespace jSonTest2.Service
{
[AspNetCompatibilityRequirements(
RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class service:IService1
{
public DB obj = new DB();//object class which return string
[WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
string IService1.JsonCall()
{
return obj.JsonCall();
throw new NotImplementedException();
}
}
}
//---------------------------------------
namespace jSonTest2.DB_provider
{
class DB//class
{
public string JsonCall()
{
string str = "{name: 'Amit', marks: 97, distinction: true}";
return str;
}
}
}
//I created a WCF service and I am not able to call any method from my angular

Related

Why is my Json string response escaped for a WCF Rest web service (weakly-typed Json) response?

I have this contract :
[ServiceContract]
public interface IServiceJsonContract
{
[WebInvoke(UriTemplate = "/MyMethod", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, Method = "POST")]
Message MyMethod(Message input);
}
And the definition for MyMethod is :
Message MyMethod(Message input)
{
...
Message response = Message.CreateMessage(
MessageVersion.None,
"*",
"{\"bla\": 2 }",
new DataContractJsonSerializer(typeof(string)));
response.Properties.Add( WebBodyFormatMessageProperty.Name,new
WebBodyFormatMessageProperty(WebContentFormat.Json));
var contextOutgoingResponse = WebOperationContext.Current.OutgoingResponse;
contextOutgoingResponse.ContentType = "application/json;charset=utf-8";
return response;
}
When calling the method I got the Json escaped:
"{\"bla\": 2 }"
instead of unescaped one (below):
"{"bla": 2 }"
Any idea how to get the unescaped Json ( "{"bla": 2 }" ) ?
Thanks
The DataContractJsonSerializer is serializing your string and escaping the quotation marks. Create a class to hold your data and pass that instead of the string.
public class MyData
{
public string Bla { get; set; }
}
// create an instance
MyData myData = new MyData()
{
Bla = "the value";
};
// then use it
Message response = Message.CreateMessage(
MessageVersion.None,
"*",
myData,
new DataContractJsonSerializer(typeof(MyData)));
you can use Stream as your out put. this way you can send back uncapped string:
[ServiceContract]
public interface IServiceJsonContract
{
[WebInvoke(UriTemplate = "/MyMethod", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, Method = "POST")]
Stream MyMethod(Message input);
}
Stream MyMethod(Message input)
{
..
return new MemoryStream(Encoding.UTF8.GetBytes("{\"bla\": 2 }"));
}

Wcf Restful service post username with parameter

I'm developer C# .Net
I Now programming a Wcf restful service for communication mobile with my server. But a problem in send json request using post method with parameter. After send request from client, server display error:
400 Bad Request...
My service contract:
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json, UriTemplate = "login", BodyStyle = WebMessageBodyStyle.WrappedRequest)]
[OperationContract]
string login(string username, string password);
And implement service:
public string login(string username, string password)
{
string str = String.Empty;
if (username == "admin" && password == "admin")
str = "Success";
else
str = "Invalid";
return str;
}
Edit:
My host is:
public void Start()
{
Stop();
//string strAdrHTTP = "http://localhost:" + HttpPort + "/WcfMobileService";
string strAdrHTTP = "http://192.168.1.190:" + HttpPort + "/WcfMobileService";
Uri[] adrbase = { new Uri(strAdrHTTP) };
m_svcHost = new ServiceHost(typeof(TWcfMobileService), adrbase);
WebServiceHost webServiceHost =
new WebServiceHost(typeof(TWcfMobileService), adrbase);
ServiceMetadataBehavior mBehave = new ServiceMetadataBehavior();
m_svcHost.Description.Behaviors.Add(mBehave);
mBehave.HttpsGetEnabled = true;
mBehave.HttpGetEnabled = true;
WebHttpBinding webBinding = new WebHttpBinding();
webServiceHost.AddServiceEndpoint(typeof(IWcfMobileServiceContract), webBinding, "rest");
WebHttpBinding restBinding = new WebHttpBinding();
ServiceEndpoint restSEP =
m_svcHost.AddServiceEndpoint(typeof(IWcfMobileServiceContract),
restBinding, "rest");
restSEP.Behaviors.Add(new WebHttpBehavior());
EndpointAddress myEndpointAdd = new EndpointAddress(new Uri(strAdrHTTP),
EndpointIdentity.CreateDnsIdentity("localhost"));
restSEP.Address = myEndpointAdd;
m_svcHost.AddServiceEndpoint(typeof(IMetadataExchange),
MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
ServiceDebugBehavior debug = new ServiceDebugBehavior();
debug.IncludeExceptionDetailInFaults = true;
m_svcHost.Open();
}
This is an working example -
[OperationContract]
[WebInvoke(
Method = "POST",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
UriTemplate = "login")]
string login(CompositeType request);
Where -
[DataContract]
public class CompositeType
{
[DataMember]
public string username { get; set; }
[DataMember]
public string password { get; set; }
}
Sample request -
{"request":{"username":"test","password":"test"}}
And it works -

WCF service doesn't recognise correct JSON

I have the following code:
[DataContract]
public class OptimizationServiceSettings
{
[DataMember]
public bool StealthMode { get; set; }
}
Server:
[WebInvoke(Method = "POST", UriTemplate = "SetSettings", BodyStyle = WebMessageBodyStyle.WrappedRequest,
ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
[OperationContract]
public void SetSettings(OptimizationServiceSettings settings)
{
if (settings != null)
{
_stageOptimizer.ServiceSettings = settings;
}
else
{
Trace.TraceError("Attemp to set null OptimizationServiceSettings");
}
}
Client:
private static void SetSettings()
{
OptimizationServiceSettings op = new OptimizationServiceSettings();
op.StealthMode = true;
string jsonInput = ToJson(op);
var client = new WebClient();
client.Headers["Content-type"] = "application/json";
client.Encoding = Encoding.UTF8;
var response = client.UploadString("http://localhost:8080/BlocksOptimizationServices/SetSettings", "POST", jsonInput);
}
private static string ToJson<T>(T data)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream())
{
serializer.WriteObject(ms, data);
return Encoding.Default.GetString(ms.ToArray());
}
}
For some reason the SetSettings method on the server always gets a null settings object. If I change the settings object type to string it all works. I don't understand what is wrong here. Everything looks like it is correct.
Here is an example of the jsonInput string that I got in SetSettings on the client:
"{\"StealthMode\":\"true\"}"
You specified the requestbody to be wrapped:
[WebInvoke(..., BodyStyle = WebMessageBodyStyle.WrappedRequest, ...]
Hence, the deserialization only succeeds if you wrap the settings-object within a containing object, as #Pankaj suggested.
Instead of doing that, you could try to change the attribute to WebMessageBodyStyle.Bare to avoid the need to wrap the parameter.

WCF JSON serialization is inconsistent so how can it be deserialized correctly?

I have a serializable polymorphic type, and a service contract.
[DataContract]
[KnownType(typeof(SomethingA))]
[KnownType(typeof(SomethingB))]
public class Something
{
[DataMember]
public int Item1 { get; set; }
[DataMember]
public string Item2 { get; set; }
}
[DataContract]
public class SomethingA : Something
{ }
[DataContract]
public class SomethingB : Something
{ }
[ServiceContract]
[ServiceKnownType(typeof(SomethingA))]
[ServiceKnownType(typeof(SomethingB))]
public interface ITesting
{
[OperationContract]
[WebInvoke(
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "use-something",
Method = "POST")]
Something UseSomething();
[OperationContract]
[WebInvoke(
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "use-polymorphic-somethings",
Method = "POST")]
List<Something> UsePolymorphicSomethings();
[OperationContract]
[WebInvoke(
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "throw-web-exception",
Method = "POST")]
void ThrowServerException();
}
...and an implementation of that contract.
using System.Net;
using System.ServiceModel.Web;
public class Testing : ITesting
{
public Something UseSomething()
{
SomethingA a = new SomethingA();
a.Item1 = 2;
a.Item2 = "b";
return a;
}
public List<Something> UsePolymorphicSomethings()
{
List<Something> retVal = new List<Something>();
retVal.Add(new SomethingA { Item1 = 1, Item2 = "1" });
retVal.Add(new SomethingB { Item1 = 1, Item2 = "1" });
return retVal;
}
public void ThrowServerException()
{
try
{
throw new ApplicationException("Bad news.");
}
catch (ApplicationException e)
{
throw new WebFaultException<ApplicationException>(e, HttpStatusCode.InternalServerError);
}
}
}
I have some functional tests in another assembly.
using System.Net;
using System.Net.Http;
using System.Runtime.Serialization.Json;
[TestMethod]
public void UseSomething_WebTest()
{
using (HttpClient http = new HttpClient())
{
http.BaseAddress = TestUtil.TestsBaseAddress;
HttpResponseMessage response = http.PostAsJsonAsync("use-something",
new StringContent(string.Empty)).Result;
string ret1 = response.Content.ReadAsStringAsync().Result;
// Deserializes SomethingA as Something.
Stream stream = response.Content.ReadAsStreamAsync().Result;
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Something));
Something ret = (Something)serializer.ReadObject(stream);
// FAILS.
Assert.AreEqual(typeof(SomethingA), ret.GetType());
}
}
[TestMethod]
public void UsePolymorphicSomethings_WebTest()
{
using (HttpClient http = new HttpClient())
{
http.BaseAddress = TestUtil.TestsBaseAddress;
HttpResponseMessage response = http.PostAsJsonAsync("use-polymorphic-somethings",
new StringContent(string.Empty)).Result;
string ret2 = response.Content.ReadAsStringAsync().Result;
// Deserializes SomethingA and SomethingB correctly.
Stream stream = response.Content.ReadAsStreamAsync().Result;
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<Something>));
List<Something> somethings = (List<Something>)serializer.ReadObject(stream);
// SUCCEEDS.
Assert.AreEqual(typeof(SomethingA), somethings[0].GetType());
Assert.AreEqual(typeof(SomethingB), somethings[1].GetType());
}
}
[TestMethod]
public void ThrowServerException1_WebTest()
{
using (HttpClient http = new HttpClient())
{
http.BaseAddress = TestUtil.TestsBaseAddress;
HttpResponseMessage response = http.PostAsync("throw-web-exception",
new StringContent(string.Empty)).Result;
Assert.AreEqual(HttpStatusCode.InternalServerError, response.StatusCode);
string ret3 = response.Content.ReadAsStringAsync().Result;
// Deserializes ApplicationException as Exception.
Stream stream = response.Content.ReadAsStreamAsync().Result;
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Exception));
Exception e = (Exception)serializer.ReadObject(stream);
// FAILS.
Assert.AreEqual(typeof(ApplicationException), e.GetType());
}
}
In UseSomething_WebTest ret1 is:
"{\"Item1\":2,\"Item2\":\"b\"}"
...with no type information embedded unsurprisingly the DataContractJsonSerializer fails to deserialize the correct type of the object that was returned.
In UsePolymorphicSomethings_WebTest ret2 is:
"[{\"__type\":\"SomethingA:#InSite8WebServiceLib\",\"Item1\":1,\"Item2\":\"1\"},{\"__type\":\"SomethingB:#InSite8WebServiceLib\",\"Item1\":1,\"Item2\":\"1\"}]"
...with type information embedded in the form of __type entries which the DataContractJsonSerializer correctly deserializes.
In ThrowServerException1_WebTest ret3 is:
"{\"ClassName\":\"System.ApplicationException\",\"Message\":\"Bad news.\",\"Data\":null,\"InnerException\":null,\"HelpURL\":null,\"StackTraceString\":\" at InSite8WebServiceLib.Testing.ThrowServerException() in d:\\\\SvnSource\\\\Hammersmith\\\\trunk\\\\VisualStudioProjects\\\\InSite8WebService\\\\InSite8WebServiceLib\\\\Testing\\\\Testing.cs:line 74\",\"RemoteStackTraceString\":null,\"RemoteStackIndex\":0,\"ExceptionMethod\":\"8\\u000aThrowServerException\\u000aInSite8WebServiceLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\\u000aInSite8WebServiceLib.Testing\\u000aVoid ThrowServerException()\",\"HResult\":-2146232832,\"Source\":\"InSite8WebServiceLib\",\"WatsonBuckets\":null}"
...with type information embedded in the form of a ClassName entry which the DataContractJsonSerializer fails to deserialize correctly.
So my question is this. Why for a single WCF WebHttp endpoint do several WebInvoke attributed methods return several different formats of JSON only one of which the DataContractJsonSerializer can actually deserialize, and how do I fix it so that it works properly?
You can force the DataContractJsonSerializer to always emit type information by overloading the constructor. Then you set the alwaysEmitTypeInformation argument to True.
Some more information on MSDN

Defining a datacontract with the same input paramiters

Is it possible to define two operation contracts with the same paramiters? I want to have the same endpoint do diffrent things on post and get. My code is below
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Xml,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "MAC/{input}")]
string MAC(string input);
[OperationContract]
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Xml,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "MAC/{input}")]
Datalayer.Datacontracts.WebserviceMessage MAC(string input);
With the same name? NO.
Using same parameters as you have mentioned is possible. But not with the same name.
Services follow document-centric paradigm; so when designing services, we should get rid of object oriented thinking. Don't think about polymorphism, overloading or overriding.
The metadata of the service has to be shared as a document to even non-object oriented systems/platforms (to support interoperability).
In addition to what SaravananArumugam said - the code as you have doesn't even compile (you cannot have two methods in the same interface with the same name whose only difference is the return type). However, you can change the method names and continue with the same UriTemplate - you'll have a "virtual" method with the same name (i.e., the address the client uses will be the same - like in the example below.
One more thing: you shouldn't use [WebInvoke(Method = "GET")], use [WebGet] instead.
public class StackOverflow_6548562
{
public class WebserviceMessage
{
public string Data;
}
[ServiceContract]
public interface ITest
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "MAC/{input}")]
string MAC_Get(string input);
[OperationContract]
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Xml,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "MAC/{input}")]
WebserviceMessage MAC_Post(string input);
}
public class Service : ITest
{
public string MAC_Get(string input)
{
return input;
}
public WebserviceMessage MAC_Post(string input)
{
return new WebserviceMessage { Data = input };
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service/";
WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
host.Open();
Console.WriteLine("Host opened");
WebClient c = new WebClient();
Console.WriteLine(c.DownloadString(baseAddress + "/MAC/fromGET"));
Console.WriteLine(c.UploadString(baseAddress + "/MAC/frompost", "POST", ""));
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}

Categories

Resources