I am connecting to an ODATA Service via a C# ASP.NET application, which has service operations such as:
GetItems(int? itemID, double? price)
I can consume this without issues in my browser, e.g.
http://api.mycompany.com/companycatalogue/GetItems?itemID=4
I understand how to use LINQ to Entities to consume an ODATA service, but can't find a decent explanation of how to consume service operations like the one above in C#. I have made a web reference to the service in my Visual Studio solution.
So far, I have something like this for my usual consuming of the data:
using CompanyCatalogue; //my web reference
...
protected void Page_Load(object sender, EventArgs e)
{
CompanyCatalogueEntities dataContext = new CompanyCatalogueEntities (new Uri("http://api.mycompany.com/companycatalogue/"));
var result = from i in dataContext.Items select i; //just an example
//this is where I get into problems
var operationResults = CompanyCatalogue.GetItems(6, 20.5); //I just made this up
}
Any pointers?
OK, got the answer:
using CompanyCatalogue; //my web reference
...
protected void Page_Load(object sender, EventArgs e)
{
CompanyCatalogueEntities dataContext = new CompanyCatalogueEntities();
DataServiceQuery<GetItemsResult> q = dataContext.CreateQuery<GetItemsResult>("GetItems")
.AddQueryOption("paramName", 6)
.AddQueryOption("paramName2", 20.5);
List<GetItemsResult> items = q.Execute().ToList();
}
This may be help for you.
This sample code used to consume the service operation in the WFC Data Service. This service operation(GetRowCount) returns the integer(int) type value. input para name is "code"
var q = context.CreateQuery<int>("GetRowCount").AddQueryOption("code", "'" + serviceProvider.Code + "'");
int RecordCount = context.Execute<int>(new Uri(q.RequestUri.ToString().Replace("GetRowCount()", "GetRowCount"))).FirstOrDefault();
Have you tried using HttpWebRequest?
Related
I try to create a simple client for WCF REST service' that I found
here.
I Added the service reference and I wrote this code:
private void button1_Click(object sender, EventArgs e)
{
WebClient proxy = new WebClient();
string serviceURL =
string.Format("http://localhost:53215/IBookService.svc/GetBooksNames");
byte[] data = proxy.DownloadData(serviceURL);
Stream stream = new MemoryStream(data);
DataContractJsonSerializer obj =
new DataContractJsonSerializer(typeof(finalProject_ClientX.ServiceReference3.Book));
finalProject_ClientX.ServiceReference3.Book book = obj.ReadObject(stream) as finalProject_ClientX.ServiceReference3.Book;
MessageBox.Show("book ID : " + book.BookName);
}
When I run the code (press the button) I get the following error:
An unhandled exception of type
'System.Runtime.Serialization.SerializationException' occurred in
System.Runtime.Serialization.dll
Additional information: The type
'finalProject_ClientX.ServiceReference3.Book' cannot be serialized to
JSON because its IsReference setting is 'True'. The JSON format does
not support references because there is no standardized format for
representing references. To enable serialization, disable the
IsReference setting on the type or an appropriate parent class of the
type.
When I run "http://localhost:53215/IBookService.svc/GetBooksNames" in the browser I got the books:
"["MVC Music Store - Tutorial -
v3.0","Pro.ASP.NET.MVC.3.Framework","Application Architecture Guide
v2","Gang of Four Design Patterns","CS4 Pocket Reference"]"
What is the problem?
Seems like Entity framework include the property IsReference = true when it add the attribute DataContract.
So , I would recommend you to include the JSON.Net nuget package in your project.
Then modify you code to something like:
private void button1_Click(object sender, EventArgs e)
{
WebClient proxy = new WebClient();
string serviceURL =
string.Format("http://localhost:53215/IBookService.svc/GetBooksNames");
byte[] data = proxy.DownloadData(serviceURL);
var jsonString = Encoding.UTF8.GetString(data);
IList<string> bookNames = JArray.Parse(jsonString).ToObject<IList<string>>();
//Do something with the list
//foreach (string bookName in bookNames)
//{
//}
}
Ok, I'm stuck. I've got a Web API that I benchmark using VS integrated Load Test project. There's one catch though, I need conditional logic. For example:
if Svc1 returns param1, then next requests should go to Svc2.
I'm using ExtractionRule to extract the parameter from web API call, and if present, add that in Context and LoadTestUserContext. Here's the code:
public override void Extract(object sender, ExtractionEventArgs e)
{
var serializer = new JsonNetSerializer();
var str = e.Response.BodyString;
var result = serializer.Deserialize<SpinResult>(str);
if (result.BonusRemainingTrials > 0)
{
e.WebTest.Context.Add("bonus", result.BonusRemainingTrials);
var userContext = (LoadTestUserContext)e.WebTest.Context["$LoadTestUserContext"];
userContext["bonus"] = result.BonusRemainingTrials;
e.Success = true;
}
}
and here's test conditional logic:
Everything works fine, until server returns the parameter, after which load test should invoke the second service (Svc2), which doesn't happen. No matter if "bonus" parameter assigned or not, the test always invokes Svc1. Any help why it's so stubborn?
Many thanks.
I need to create an application that gets the stock value of a corporation using web services. I currently have a reference to the web service but I do not know how to parse the XML string I get. How do I select just the stock value?
protected void Button1_Click(object sender, EventArgs e)
{
StockRefrence.StockQuote callWeb = new StockRefrence.StockQuote();
string stock = callWeb.GetQuote("CSCO");
Label1.Text = stock;
}
The web service I'm using http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2
You probably want to use XPath:
.Net XPath Examples
I am creating a WCF web api service. My problem is that some methods return a 200/OK response, but the headers and the body are empty.
In setting up my web service, I created an ADO.NET Entity Data Model. I chose ADO.NET DbContext Generator when I added a code generation item. In the Model.tt document, I changed HashSet and ICollection to List. I built my website.
It used to be that when I coded a method to return a List of an entity (like List<Customer> or List<Employee> in the Northwind database), it worked fine. Over time, I could not return a List of any of those, and could only grab one entity. Now, it's gotten to a point where I can return a List<string> or List<int>, but not a List or an instance of any entity. When I try to get a List<AnyEntity>, the response is 200/OK, but the response headers and body are empty.
I have tried using the debugger and Firefox's Web Console. Using FF's WC, I could only get an "undefined" status code. I am not sure where to go from here.
EDIT: In trying to grab all Areas from the database, I do this:
[WebGet(UriTemplate = "areas")]
public List<a1Areas> AllAreas()
{
return context.a1Areas.ToList();
}
I would appreciate any more methods for debugging this. Thanks in advance.
Found the answer, thanks to Merlyn!
In my Global.asax file, I forgot to comment out two lines that took care of proxies and disposing of my context object. The code is below:
void Application_BeginRequest(object sender, EventArgs e)
{
var context = new AssignmentEntities();
context.Configuration.ProxyCreationEnabled = false;
HttpContext.Current.Items["_context"] = context;
}
void Application_EndRequest(object sender, EventArgs e)
{
var context = HttpContext.Current.Items["_context"] as AssignmentEntities;
if (context != null)
{
context.Dispose();
}
}
I'm creating a simple Silverlight 2 application - a guestbook. I'm using MSSQL as the data source, I've managed to load the data but I can't find out how to add new rows (messages) to the database.
I crawled all the internet but didn't find any working solution. The SCMEssages table has four columns - MessageID, MessageDate, MessageAuthor and MessageText. Right now I have the following code in Service1 class (which implements IService1 interface) (not working though):
public void SaveMessage(SCMessage message)
{
DataClasses1DataContext db=new DataClasses1DataContext();
db.GetTable<SCMessage>().Attach(message);
db.SubmitChanges();
}
In the main class I'm simply calling this method:
private void SendBtn_Click(object sender, RoutedEventArgs e)
{
SCMessage sm = new SCMessage
{
MessageAuthor = NameTB.Text,
MessageDate = DateTime.Now,
MessageText = TextTB.Text
};
newMessages.Add(sm);
ServiceReference1.Service1Client client = new Service1Client();
client.SaveMessageAsync(sm);
}
Could anybody help me? Thanks for any suggestions!
I'm not sure I complete understand the context (like do you control your WCF service and/or your DB). But did you consider ADO.Net Data services? (also known as astoria)
(http://msdn.microsoft.com/en-us/library/cc668792.aspx)
Then you don't need to create a webservice for it, it is already created for you.
Basically it is an easy way to access your data from within Silverlight and even be able to do queries from within silverlight.
There is already a bit of doc in blogs, for example:
A quickstart is here: http://michaelsync.net/2008/01/15/consuming-adonet-data-service-astoria-from-silverlight
How to update data can be seen here: http://michaelsync.net/2008/02/10/crud-operations-in-siverlight-using-adonet-data-service
A complete working example is here: http://www.silverlightdata.com/
Note that in a lot of examples on the web the silverlight proxy is generated using the command line, that is however not needed anymore, you can do it directly from within VS using "add service reference" to your project and pointing it to your ado.net data service
Hope this helps a bit?
Tjipke
Is SCMessage decorated with the [DataContract] attribute or is it [Serializable]? Please provide us with the definition of SCMessage.
SCMessage is name of a Data Class - I created a file from template "Linq to SQL Classes" (.dbml) and drag&dropped the SCMessages table to the Designer. It's decorated with the [DataContract] attribute and I set it's DataContext's Serialiation Mode property to Unidirectional. So the content of the SCMessage class is auto-generated, but here is as least a part of it:
[Table(Name="dbo.SCMessages")]
[DataContract()]
public partial class SCMessage : INotifyPropertyChanging, INotifyPropertyChanged
{
private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
private int _MessageID;
private string _MessageAuthor;
private string _MessageText;
private System.DateTime _MessageDate;
#region Extensibility Method Definitions
partial void OnLoaded();
partial void OnValidate(System.Data.Linq.ChangeAction action);
partial void OnCreated();
partial void OnMessageIDChanging(int value);
partial void OnMessageIDChanged();
partial void OnMessageAuthorChanging(string value);
partial void OnMessageAuthorChanged();
partial void OnMessageTextChanging(string value);
partial void OnMessageTextChanged();
partial void OnMessageDateChanging(System.DateTime value);
partial void OnMessageDateChanged();
#endregion
public SCMessage()
{
this.Initialize();
}
[Column(Storage="_MessageID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
[DataMember(Order=1)]
public int MessageID
{
get
{
return this._MessageID;
}
set
{
if ((this._MessageID != value))
{
this.OnMessageIDChanging(value);
this.SendPropertyChanging();
this._MessageID = value;
this.SendPropertyChanged("MessageID");
this.OnMessageIDChanged();
}
}
}
And here's a little problem with Astoria - it doesn't work for me. I followed the Michael Sync's tutorial and made a few modifications, such as using of DataServiceQuery because WebDataQuery doesn't exist in final version of Astoria, etc. I ended up with two code snippets - the first is almost identical copy of the one in Michael Sync's article and the second one is using LINQ query instead of the CreateQuery method (I think both of these approaches lead to the same end). Here are the snippets:
SilverchatDBEntities entity =
new SilverchatDBEntities(new Uri("http://localhost:65373/WebDataService1.svc", UriKind.Absolute));
entity.MergeOption = MergeOption.OverwriteChanges;
DataServiceQuery<SCMessages> messages = entity.CreateQuery<SCMessages>("SCMessages");
messages.BeginExecute(
result =>
{
var mess = messages.EndExecute(result);
foreach (var mes in mess)
{
MessagesLB.Items.Add(mes.MessageAuthor);
}
},
null);
This doesn't do anything - it doesn't throw any exception and doesn't load any SCMessages neither. The second snippet is as follows:
SilverchatDBEntities entity =
new SilverchatDBEntities(new Uri("http://localhost:65373/WebDataService1.svc", UriKind.Absolute));
var query = (DataServiceQuery<SCMessages>) from m in entity.SCMessages select m;
query.BeginExecute(new AsyncCallback(result =>
{
try
{
var mes = query.EndExecute(result);
foreach (var r in mes)
{
MessagesLB.Items.Add(string.Format("{0}; {1} - {2}",
r.MessageDate.
ToString(
"d/M hh:mm",
CultureInfo.
InvariantCulture),
r.MessageAuthor,
r.MessageText));
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}), null);
This one throws exception at the 'foreach' loop - 'Object reference not set to an instance of an object'. I have no idea what the problem could be.
Chrasty,
I don't see any obvious errors yet. So in theory it shoulld work (I currently work almost daily with these kind of queries. A few questions:
1. can you use fiddler2 to see what is going over the wire. (If you don't know what fiddler is then google :-) and if after that you are using fiddler on localhost, then please add a '.' in the url in the browser (like http:\localhost.:1234\mywebsitehostingsilverlight.aspx), -> prevents an other google search)
2. Do you have a stack trace of the second one throwing an exception.
3. Did you try putting a breakpoint in your callback (first example) to see if it is called and with what result it is called
Hope these questions help a bit in solving the problem