I am trying to use protobuf format in ServiceStack Webservices ( following the example at ServiceStack: REST with ProtoBuf by Steven Hollidge. I have added a Winform application to consume the webservice. The codes are given below.
HelloService.cs
using System.Runtime.Serialization;
using ProtoBuf;
using ServiceStack.Demo.Rest;
using ServiceStack.ServiceHost;
using ServiceStack.ServiceInterface;
namespace ServiceStack.Demo.WebService
{
[DataContract]
public class Hello
{
[DataMember(Order = 1)]
public string Name { get; set; }
}
[DataContract]
public class HelloResponse
{
[DataMember(Order = 1)]
public string Result { get; set; }
}
public class HelloService : RestServiceBase<Hello>
{
public override object OnGet(Hello request)
{
return new HelloResponse { Result = "Hello, " + request.Name };
}
}
}
Global.asax.cs
using System;
using System.Web;
using Funq;
using ServiceStack.Demo.Rest;
using ServiceStack.Demo.WebService;
using ServiceStack.WebHost.Endpoints;
namespace ServiceStack.Demo
{
public class AppHost : AppHostBase
{
public AppHost() : base("ServiceStack makes services easy!", typeof (AppHost).Assembly)
{
ServiceStack.Plugins.ProtoBuf.AppStart.Start();
}
public override void Configure(Container container)
{
Routes
.Add<Hello>("/hello")
.Add<Hello>("/hello/{Name}");
}
}
public class Global : HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
new AppHost().Init();
}
}
}
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ServiceStack.ServiceClient;
using ProtoBuf;
using ServiceStack.Plugins.ProtoBuf;
using System.Runtime.Serialization;
using ServiceStack.ServiceClient.Web;
namespace client
{
public partial class Form1 : Form
{
private ServiceClientBase _client;
private const string Url = "http://localhost/servicestack.demo/servicestack/hello?format=x-protobuf";
public Form1()
{
InitializeComponent();
}
private void Button1Click(object sender, EventArgs e)
{
this._client =
new ProtoBufServiceClient(Url);
var response = _client.Send<HelloResponse>(new Hello {Name = "ProtoBuf"});
label1.Text = response.Result;
}
public class Hello
{
public string Name { get; set; }
}
public class HelloResponse
{
public string Result { get; set; }
}
}
}
I am getting System.InvalidOperationException: Type is not expected, and no contract can be inferred: client.Form1+Hello
What am I doing wrong? Please suggest.....
It looks like you have your Hello class and your HelloResponse class declared twice. Once in HelloService.cs and again as inner classes in Form.cs. Removing the duplicates from your Form.cs file should allow your ProtoBufServiceClient to reference the correct classes/types.
I have updated the Form1.cs to the following and now it is working fine( refer to http://upjnv.blogspot.in/
using System;
using System.Windows.Forms;
using ServiceStack.Plugins.ProtoBuf;
using System.Runtime.Serialization;
using ServiceStack.ServiceClient.Web;
namespace client
{
public partial class Form1 : Form
{
private ServiceClientBase _client;
private const string Url = "http://localhost/servicestack.demo/servicestack/";
public Form1()
{
InitializeComponent();
}
private void Button1Click(object sender, EventArgs e)
{
this._client =
new ProtoBufServiceClient(Url);
var response = _client.Send<HelloResponse>("GET","/hello",new Hello {Name = "ProtoBuf"});
label1.Text = response.Result;
}
}
[DataContract]
public class Hello
{
[DataMember(Order = 1)]
public string Name { get; set; }
}
[DataContract]
public class HelloResponse
{
[DataMember(Order = 1)]
public string Result { get; set; }
}
}
Put your POCO classes in the same namespace, that should do it.
Related
I am trying to fetch data from 000webhost server into my xamarin.android application. connection of php mysqldatabase is working good but I am getting JSONException in one of my classes shown below.
DataPhraser.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Java.Lang;
using Org.Json;
using Object = Java.Lang.Object;
using String = System.String;
namespace database_test.database.mySQL
{
class DataPhraser : AsyncTask
{
Context c;
private Spinner sp;
private String jsonData;
JavaList<string> Universities = new JavaList<string>();
private ProgressDialog pd;
public DataPhraser(Context c, Spinner sp, string jsonData)
{
this.c = c;
this.sp = sp;
this.jsonData = jsonData;
}
protected override void OnPreExecute()
{
base.OnPreExecute();
pd = new ProgressDialog(c);
pd.SetTitle("Parse Data");
pd.SetMessage("Parsing Data..... Please Wait");
pd.Show();
}
protected override Object DoInBackground(params Object[] #params)
{
//throw new NotImplementedException();
return this.ParseData();
}
protected override void OnPostExecute(Object result)
{
base.OnPostExecute(result);
pd.Dismiss();
if (Integer.ParseInt(result.ToString()) == 0)
{
Toast.MakeText(c, "unable to Prase", ToastLength.Short).Show();
}
else
{
ArrayAdapter<string> adapter = new ArrayAdapter<string>(c, Android.Resource.Layout.SimpleListItem1, Universities);
sp.Adapter = adapter;
sp.ItemSelected += sp_ItemSelected;
}
}
private void sp_ItemSelected(object sender, AdapterView.ItemSelectedEventArgs e)
{
Toast.MakeText(c, Universities[e.Position], ToastLength.Short).Show();
}
private int ParseData()
{
try
{
JSONArray ja = new JSONArray(jsonData);
JSONObject jo = null;
Universities.Clear();
for (int i = 0; i < ja.Length(); i++)
{
jo = ja.GetJSONObject(i);
String name = jo.GetString("Country");
Universities.Add(name);
}
return 1;
}
catch (System.Exception e)
{
Console.WriteLine(e);
}
return 0;
}
}
}
I am getting error at " JSONArray ja = new JSONArray(jsonData)" this point of the code.
Mysqldatabase is
According to your gson, you can try to use Newtonsoft.Json Nuget ,for example:
namespace QuickType
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public partial class Welcome
{
[JsonProperty("Options")]
public Option[] Options { get; set; }
}
public partial class Option
{
[JsonProperty("ID")]
public long Id { get; set; }
[JsonProperty("University Name")]
public string UniversityName { get; set; }
[JsonProperty("Country")]
public string Country { get; set; }
[JsonProperty("Course")]
public string Course { get; set; }
[JsonProperty("Field of Study")]
public string FieldOfStudy { get; set; }
[JsonProperty("Course Language")]
public string CourseLanguage { get; set; }
[JsonProperty("Type of Institution")]
public string TypeOfInstitution { get; set; }
}
public partial class Welcome
{
public static Welcome FromJson(string json) => JsonConvert.DeserializeObject<Welcome>(json, QuickType.Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this Welcome self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
}
internal static class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
new IsoDateTimeConverter { DateTimeStyles =
DateTimeStyles.AssumeUniversal }
},
};
}
}
For more details, you can check: https://app.quicktype.io/#l=cs&r=json2csharp
Note: you can just copy your json string to the left part of above link, then it will convert the json into relative data models.
I am try to read data from this JSON file http://www.astro-phys.com/api/de406/states?date=1000-1-20&bodies=mars the date reads fine but I want to read :
[-168045229.22750974, 164411532.90034229, 80245103.265201837]
But as the data doesn't have a name I don't know how. This is my current code
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
using System.Windows.Forms;
namespace Planets
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void pictureBox1_Click(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
string filecontents;
string pagerequest = "http://www.astro-phys.com/api/de406/states?date=1000-1-20&bodies=mars";
WebRequest request = WebRequest.Create(#pagerequest);
WebResponse response = request.GetResponse();
Stream data = response.GetResponseStream();
string html = string.Empty;
using (StreamReader sr = new StreamReader(data))
{
filecontents = sr.ReadToEnd();
}
JavaScriptSerializer jsonSerialiser = new JavaScriptSerializer();
Results results = jsonSerialiser.Deserialize<Results>(filecontents);
richTextBox1.Text = (results.date);
Console.Write(results.date);
Console.ReadLine();
}
}
public class Results
{
public string date { get; set; }
public Position position { get; set; }
}
//public class Position
//{
// public int x { get; set; }
// public int y { get; set; }
//}
}
I am brand new to this and any help would be appreciated
Thanks
Your Results class should look something like this
public class Results
{
public string date { get; set; }
public IDictionary<string, IList<decimal[]>> results { get; set; }
public string unit { get; set; }
}
This allows for multiple planetary data points to be defined in the JSON.
i.e. if you were to call http://www.astro-phys.com/api/de406/states?date=1000-1-20&bodies=mars,earth would return mars and earth etc.
Then to access a specific co-ordinates
var coord1 = results.results["mars"][0][0]; // -168045229.22750974
var coord2 = results.results["mars"][0][1]; // 164411532.90034229
var coord3 = results.results["mars"][0][2]; // 80245103.265201837
i created a json file on my server which im using to send data to a c# program through JSON.NET deserialize. However im im getting a null object exception, can anyone please show me how to create the classes. Thanks
My class is here
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Newtonsoft.Json;
namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Load();
}
public void Load()
{
label1.Text = "State:\nLoading...";
try
{
Products pd = new Products();
using (var webClient = new System.Net.WebClient())
{
// download json from url
var json = webClient.DownloadString(url);
// Now parse with JSON.Net
Products convert = JsonConvert.DeserializeObject<Products>(json) as Products;
label1.Text += pd.info.ToString();
label1.Text += "\nWeb Service Connected To";
}
}
catch (JsonSerializationException jsonerr) { label1.Text += "\nWeb Service Connection Failed"; MessageBox.Show(jsonerr.ToString()); }
catch (Exception err) { throw; }
finally { label1.Text += "\nWeb Service Closed"; }
}
}
}
public class Products
{
public Info info;
[JsonProperty("post")]
public Info infos
{
get { return info; }
set { info = value; }
}
}
public class Info
{
private string pd_name;
private int pd_id;
[JsonProperty("pd_id")]
public int pd_ids
{
get { return pd_id; }
set { pd_id = value; }
}
[JsonProperty("pd_name")]
public string pd_names
{
get { return pd_name; }
set { pd_name = value; }
}
}
You're not handling the posts value in the JSON. So if your JSON is formatted like this:
{ "posts" : [ { "post" : { "pd_id" : "399",
"pd_name" : "1.2mm Cylinder Labret"} },
{ "post" : { "pd_id" : "415",
"pd_name" : "1.2mm Laser Etched Labret" }}
] }
Try setting up your classes like this:
public class Posts
{
public List<Products> posts { get; set; }
}
public class Products
{
public List<Info> post { get; set; }
}
public class Info
{
public string pd_id { get; set; }
public string pd_name {get; set; }
}
I would like to deserialize the following XML into the following type. How do I map the status correctly? (it is currently not mapped and remains null after the deserialization process)
<?xml version="1.0" encoding="UTF-8"?>
<job:job-status xsi:schemaLocation="http://marklogic.com/xdmp/job-status job-status.xsd" xmlns:job="http://marklogic.com/xdmp/job-status" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<job:forest>
<job:forest-name>FOREST2</job:forest-name>
<job:forest-id>1168048654236455340</job:forest-id>
<job:status>completed</job:status>
<job:journal-archiving>false</job:journal-archiving>
</job:forest>
</job:job-status>
[XmlRoot("job-status", Namespace = "http://marklogic.com/xdmp/job-status")]
public class DatabaseRestoreStatus
{
[XmlElement("status")]
public string Status { get; set; }
}
Using DataContract Serializer worked for me. I also had to create one more class.
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
namespace SandboxConoleApp
{
internal class Program
{
private static void Main(string[] args)
{
DatabaseRestoreStatus data = null;
using (var stream = File.Open("test.xml",FileMode.Open))
{
var formatter = new DataContractSerializer(typeof(DatabaseRestoreStatus));
data = (DatabaseRestoreStatus)formatter.ReadObject(stream);
}
}
}
[DataContract(Name = "job-status", Namespace = "http://marklogic.com/xdmp/job-status")]
public class DatabaseRestoreStatus
{
[DataMember(Name = "forest")]
public Forest Forest { get; set; }
}
[DataContract(Name = "forest", Namespace = "http://marklogic.com/xdmp/job-status")]
public class Forest
{
[DataMember(Name = "status")]
public string Status { get; set; }
}
}
I am getting the following exception when I call the WCF Service from ASP.NET website. How can we overcome it?
Note: By applying break point in service project, I have verified that the service is returning two valid objects.
Note: In service, I am returing List of IBankAccount. [OperationContract]
List<IBankAccount> GetDataUsingDataContract(int userId); The IBankAccount is an interface.
The exception says "The underlying connection was closed: The connection was closed unexpectedly". Detailed stack trace is available in the following picture.
//Website
using System;
using ServiceReference1;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Service1Client client = new Service1Client();
string result = client.GetData(1);
Response.Write(result);
client.GetDataUsingDataContract(1);
int d = 0;
}
}
//Service Interface
using System.Collections.Generic;
using System.ServiceModel;
using DTOProject;
namespace MyServiceApp
{
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
[OperationContract]
List<IBankAccount> GetDataUsingDataContract(int userId);
}
}
//DTO
using System.Runtime.Serialization;
namespace DTOProject
{
public interface IBankAccount
{
int Duration { get; set; }
int AmountDeposited { get; set; }
}
}
using System.Runtime.Serialization;
namespace DTOProject
{
[DataContract]
public class FixedAccount : IBankAccount
{
[DataMember]
public int Duration { get; set; }
[DataMember]
public int AmountDeposited { get; set; }
}
}
using System.Runtime.Serialization;
namespace DTOProject
{
[DataContract]
public class SavingsAccount : IBankAccount
{
[DataMember]
public int Duration { get; set; }
[DataMember]
public int AmountDeposited { get; set; }
}
}
//Service Implementation
using System.Collections.Generic;
using DTOProject;
using BusinessLayer;
namespace MyServiceApp
{
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public List<IBankAccount> GetDataUsingDataContract(int userId)
{
BusinessLayer.AccountManager accManager = new AccountManager();
List<IBankAccount> accounts = accManager.GetAllAccountsForUser(userId);
return accounts;
}
}
}
//Business Layer
using System.Collections.Generic;
using DTOProject;
using DataAccessLayer;
namespace BusinessLayer
{
public class AccountManager
{
public List<IBankAccount> GetAllAccountsForUser(int userID)
{
DataAccessLayer.AccounutManagerDAL accountManager = new AccounutManagerDAL();
List<IBankAccount> accountList = accountManager.GetAllAccountsForUser(userID);
return accountList;
}
}
}
//Data Access Layer
using System;
using System.Collections.Generic;
using DTOProject;
namespace DataAccessLayer
{
public class DatabaseRecordSimulation
{
public string AccountType { get; set; }
public int Duration { get; set; }
public int DepositedAmount { get; set; }
}
public class AccounutManagerDAL
{
List<DatabaseRecordSimulation> dbRecords = new List<DatabaseRecordSimulation>()
{
new DatabaseRecordSimulation{AccountType="Savings",Duration=6,DepositedAmount=50000},
new DatabaseRecordSimulation{AccountType="Fixed",Duration=6,DepositedAmount=50000}
};
public List<IBankAccount> GetAllAccountsForUser(int userID)
{
List<IBankAccount> accountList = new List<IBankAccount>();
foreach (DatabaseRecordSimulation dbRecrod in dbRecords)
{
IBankAccount acc = AccountFactory.GetAccount(dbRecrod);
accountList.Add(acc);
}
return accountList;
}
}
public static class AccountFactory
{
public static IBankAccount GetAccount(DatabaseRecordSimulation dbRecord)
{
IBankAccount theAccount = null;
if ( String.Equals(dbRecord.AccountType, "Fixed"))
{
theAccount = new FixedAccount();
}
if (String.Equals(dbRecord.AccountType, "Savings"))
{
theAccount = new SavingsAccount();
}
return theAccount;
}
}
}
READING:
1. WCF Object Design - OOP vs SOA
As per this post:
http://social.msdn.microsoft.com/Forums/eu/wcf/thread/31102bd8-0a1a-44f8-b183-62926390b3c3
You cannot return an interface - you must return a class. However, you can create an abstract base type - BankAccount and apply the KnownType attribute to it. For example:
[DataContract]
[KnowType(typeof(FixedAccount))]
[KnowType(typeof(SavingsAccount))]
abstract class BankAccount { ... }
[DataContract]
class FixedAccount : BankAccount { ... }
[DataContract]
class SavingsAccount : BankAccount { ... }
The KnownType attribute let's WCF know that some other type, not explicitly referenced in the service contract will be a part of the contract.