Consuming WCF service in objective C - objective-c

I m new to iPhone programming.
What I want to do authenticate a user in iPhone using webservice. For instance
I Have a WCF webservice that I want to consume in my objective C code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Runtime.Serialization;
using MobileKpi.Business;
namespace MobileKpi.Services
{
[ServiceContract]
public interface IUploadData
{
[OperationContract]
[WebInvoke(UriTemplate = "UploadUserSessionData/", Method = "POST")]
string UploadUserSessionData(SessionXML pstrXML);
}
[DataContract(Namespace = "", Name = "UserLogin")]
public class UserLogin
{
string user = "";
string pass = "";
[DataMember(Name = "userName")]
public string userName
{
get { return user; }
set { user = value; }
}
[DataMember(Name = "password")]
public string password
{
get { return pass; }
set { pass = value; }
}
}
}
I want to access its two data members user and password . How can I do it in Objective C.
Any solutions Or Sample Code.

One place you could start is reviewing the code in the answer of this SO question. It shows how to send JSON but you could tweak it to work with XML instead. In your code, you don't show how you expect UserLogin to be sent to the service. You could add it as a parameter as follows:
[ServiceContract]
public interface IUploadData
{
[OperationContract]
[WebInvoke(UriTemplate = "UploadUserSessionData/", Method = "POST")]
string UploadUserSessionData(SessionXML pstrXML, UserLogin credentials);
}

Related

Does WCF OData Service Support Projection?

I'm using WCF OData service as my application Data Provider.OData service expose a entity that I don't want to get whole entity,I create LINQ query to get projection from this Entity.
But i have error in OData Service.This is my code:
from n in NewsInfos
select new NewsInfos
{
n.NewsId,
n.NewsTitle,
n.NewsLead,
n.NewsDate
};
This is entire code:
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class NewsDataService : DataService<NewsODataModel>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
config.DataServiceBehavior.AcceptProjectionRequests = true;
}
}
Yes, WCF Data Services and OData support projection. Projection is codified in the URL with the $select system query option, e.g.: http://services.odata.org/Experimental/OData/OData.svc/Products?$select=Name&$format=json. The LINQ Provider in the client bits enable this similarly to what you've shown in your example. Here is one such example:
using System;
using System.Data.Services.Client;
using System.Linq;
namespace Scratch
{
public class Program
{
public static void Main()
{
var context = new DataServiceContext(new Uri("http://services.odata.org/OData/OData.svc/"));
var categories = context.CreateQuery<Category>("Categories").Select(c => new { c.Name });
Console.WriteLine("context.Categories.Where(...): {0}", categories);
foreach (var category in categories)
{
Console.WriteLine(category.Name);
}
}
}
public class Category
{
public int ID { get; set; }
public string Name { get; set; }
}
}
One thing to consider with projection is that the magic in our client-side bits frequently requires you to use anonymous objects (hence the new { c.Name }).
Your error may be unrelated; if you're still getting the error after reading this can you update your service to return verbose errors as per http://blogs.msdn.com/b/phaniraj/archive/2008/06/18/debugging-ado-net-data-services.aspx? My guess is that you may be missing the [DataServiceKey] attribute on NewsInfos.
Just return an anonymous object from your select and it should work.
from n in NewsInfos
select new
{
n.NewsId,
n.NewsTitle,
n.NewsLead,
n.NewsDate
};

How to access custom attributes defined in WCF service using C#?

First question is, how can I get the type of an object stored in a variable? Generally we do:
Type t = typeof(ClassName); //if I know the class
but, how can I say something:
Type t = typeof(varClassName); //if the class name is stored in a variable
Second question, a broader picture is, I have a WCF service that contains a DataContract class say "MyClass" and I have defined a custom attribute called "MyAttribute" to it. There is one method say "GetDataUsingDataContract" with a parameter of type MyClass. Now on client, I invoke the webservice. I use MethodInfo and ParameterInfo classes to get the parameters of the method in question. But how can I access the attributes of the method parameter which is actually a class Myclass? Here is the code that I tried:
MyService.Service1Client client = new MyService.Service1Client();
Type t = typeof(MyService.Service1Client);
MethodInfo members = t.GetMethod("GetDataUsingDataContract");
ParameterInfo[] parameters = members.GetParameters();
foreach (var parameter in parameters)
{
MemberInfo mi = parameter.ParameterType; //Not sure if this the way
object[] attributes;
attributes = mi.GetCustomAttributes(true);
}
Above code doesn't retrieve me the custom attribute "MyAttribute". I tried the concept in the class that is defined in the same project and it works. Please HELP!
but, how can I say something:
Type t = typeof(varClassName); //if the class name is stored in a variable
Try
Type.GetType("varClassName", false, true);
As to your second question:
Above code doesn't retrieve me the
custom attribute "MyAttribute". I
tried the concept in the class that is
defined in the same project and it
works. Please HELP!
Just guessing, I'm not sure that attributes are exposed to the client, by default. I think its the same issue as an untrusted assembly. Some attributes are sensitive info. See this:
http://blogs.msdn.com/b/haibo_luo/archive/2006/02/21/536470.aspx
But you could try linking the service project types into your app by first referencing the service assembly in your client project, then going to your service reference -> "Configure Service Reference" and selecting "Reuse types in all referenced assemblies". I'm not sure this option will affect the service interface classes, but I use it often with my domain objects. Worth a try.
Type mi = parameter.ParameterType; //Not sure if this the way
object[] attributes;
attributes = mi.GetCustomAttributes(true);
Ensure your proxy class has knowledge on attributes
Hope this will help
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 System.ServiceModel;
using System.Runtime.Serialization;
using System.Reflection;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
StartService();
}
string url = "http://localhost:234/MyService/";
private void StartClient()
{
IMyService myService = ChannelFactory<IMyService>.CreateChannel(new BasicHttpBinding(), new EndpointAddress(url));
Type t = typeof(IMyService);
MethodInfo members = t.GetMethod("MyMethod");
ParameterInfo[] parameters = members.GetParameters();
foreach (var parameter in parameters)
{
Type mi = parameter.ParameterType;
object[] attributes;
attributes = mi.GetCustomAttributes(true);
}
}
private void StartService()
{
ServiceHost host = new ServiceHost(typeof(MyService), new Uri(url));
host.AddServiceEndpoint(typeof(IMyService), new BasicHttpBinding(), "");
host.Open();
}
private void button1_Click(object sender, EventArgs e)
{
StartClient();
}
}
[AttributeUsage(AttributeTargets.Interface)]
public class MyAttrib : Attribute
{
}
[MyAttrib]
public interface IMyContract
{
string Name { get; set; }
}
[DataContract]
public class MyContract : IMyContract
{
[DataMember]
public string Name { get; set; }
}
[ServiceContract]
public interface IMyService
{
[OperationContract]
bool MyMethod(IMyContract dummy);
}
[ServiceBehavior(UseSynchronizationContext = false)]
public class MyService : IMyService
{
public bool MyMethod(IMyContract dummy)
{
return true;
}
}
}

Passing DTO's from a seperate Project to UI Layer WCF RIA services

I have a solution that I have designed with 5 layers.
They are:
UI/Presentation Layer
Service Layer
Business Logic Layer
Data Access Layer
DTO/Common Layer (IQUTECHDTO)
I want to pass the DTO to the UI. Below is the service layer that exposes a method GetVendors which I want to return the VendorDTO. This object will populate a drop down box.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;
using IQUTechDTO;
using IQUTECHDAL;
namespace BusinessApplication6.Web.Services
{
public class Foos
{
[Key]
public int FooId { get; set; }
public string Name { get; set; }
}
// TODO: Create methods containing your application logic.
[EnableClientAccess()]
public class BillService : DomainService
{
public IEnumerable<Foos> GetFoos()
{
return new List<Foos> { new Foos { FooId = 42, Name = "Fred" } };
}
[Query]
public IEnumerable<VendorDTO> GetVendors()
{
return new List<VendorDTO> { new VendorDTO { VendorID = 42 } };
}
}
}
On the UI .cs file when I try and create an object of type VendorDTO I cannot. I was however able to access the Foo object from the UI Layer.
The VendorDTO was marked as serialazble but it does however reside in a seperate project (IQUTECHDTO)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using System.ServiceModel.DomainServices;
using System.ServiceModel.Web;
namespace IQUTechDTO
{
public enum LoadStatus
{
Initialized = 0,
Ghost = 1,
Loaded = 2
}
[Serializable]
public class VendorDTO
{
/// <summary>
///DTO for the 'Vendor' object.
/// </summary>
public VendorDTO()
{
this.loadStatus = LoadStatus.Initialized;
}
///<summary>
/// Copy constructor
///</summary>
public VendorDTO(VendorDTO sourceDTO)
{
loadStatus = sourceDTO.loadStatus;
VendorID = sourceDTO.VendorID;
VendorName = sourceDTO.VendorName;
VendorAddress1 = sourceDTO.VendorAddress1;
VendorAddress2 = sourceDTO.VendorAddress2;
VendorCity = sourceDTO.VendorCity;
VendorState = sourceDTO.VendorState;
VendorEmail = sourceDTO.VendorEmail;
VendorPhone = sourceDTO.VendorPhone;
VendorPOC = sourceDTO.VendorPOC;
VendorRegion = sourceDTO.VendorRegion;
}
public LoadStatus loadStatus;
[Key]
public int VendorID { get; set; }
public string VendorName;
private string VendorAddress1;
private string VendorAddress2;
private string VendorEmail;
private string VendorPhone;
private string VendorCity;
private string VendorState;
private string VendorPOC;
private string VendorRegion;
}
}
Below is the UI Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using BusinessApplication6.Web.Services;
using System.ServiceModel.DomainServices.Client;
using BusinessApplication6.Web;
namespace BusinessApplication6.Views.BOM
{
public partial class BOMCRUD : Page
{
public BOMCRUD()
{
InitializeComponent();
LoadTree();
}
public void LoadTree()
{
BillContext newCon = new BillContext();
//This works
Foos fooobj = new Foos();
//This doesnt work
VendorDTO vendorobj = new VendorDTO();
}
// Executes when the user navigates to this page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
}
}
Why will it not let me access this object.
Your help would be greatly appreciated.
Regards,
Tom
The UI class has doesn't have a reference to IQUTECHDTO like the Foos class does(in BusinessApplication6.Web).

SilverLight Enabled Wcf Service - can't keep track of session

I'm new to Silverlight and WCF services. I'm trying to write a client application that can manipulate an object server side.
My problem is that each time my Silverlight client makes a call to the service, it enters into the constructor systematically
public SilverLightEnabledWcfService()
{
}
In the below example, I simply want to increment or decrement a number depending on the activity client side.
How am I supposed to do this properly?
I also tried to create a regular ASP.net client page and I got the same result, ie the server doesn't remember the session. So I don't think the problem is in my client, but I'm still happy to post the code if it helps.
Thanks !!
using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using Count.Library;
namespace Count.WebApp
{
[ServiceContract(Namespace = "")]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class SilverLightEnabledWcfService
{
public SilverLightEnabledWcfService()
{
}
private Class1 _class1;
[OperationContract]
public int Add1()
{
if (_class1 == null)
_class1 = new Class1(0);
_class1.Add1();
return Value;
}
[OperationContract]
public int Remove1()
{
if (_class1 == null)
_class1 = new Class1(0);
_class1.Remove1();
return Value;
}
public int Value
{
get
{
return _class1.Count;
}
}
}
}
Sessions require the wsHttpBinding, but this is not supported by Silverlight. There are workarounds, though:
http://web-snippets.blogspot.com/2008_08_01_archive.html
http://forums.silverlight.net/forums/t/14130.aspx

How do I authenticate a WCF Data Service?

I've created an ADO.Net WCF Data Service hosted in a Azure worker role. I want to pass credentials from a simple console client to the service then validate them using a QueryInterceptor. Unfortunately, the credentials don't seem to be making it over the wire.
The following is a simplified version of the code I'm using, starting with the DataService on the server:
using System;
using System.Data.Services;
using System.Linq.Expressions;
using System.ServiceModel;
using System.Web;
namespace Oslo.Worker
{
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
public class AdminService : DataService<OsloEntities>
{
public static void InitializeService(
IDataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
}
[QueryInterceptor("Pairs")]
public Expression<Func<Pair, bool>> OnQueryPairs()
{
// This doesn't work!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (HttpContext.Current.User.Identity.Name != "ADMIN")
throw new Exception("Ooops!");
return p => true;
}
}
}
Here's the AdminService I'm using to instantiate the AdminService in my Azure worker role:
using System;
using System.Data.Services;
namespace Oslo.Worker
{
public class AdminHost : DataServiceHost
{
public AdminHost(Uri baseAddress)
: base(typeof(AdminService), new Uri[] { baseAddress })
{
}
}
}
And finally, here's the client code.
using System;
using System.Data.Services.Client;
using System.Net;
using Oslo.Shared;
namespace Oslo.ClientTest
{
public class AdminContext : DataServiceContext
{
public AdminContext(Uri serviceRoot, string userName,
string password) : base(serviceRoot)
{
Credentials = new NetworkCredential(userName, password);
}
public DataServiceQuery<Order> Orders
{
get
{
return base.CreateQuery<Pair>("Orders");
}
}
}
}
I should mention that the code works great with the signal exception that the credentials are not being passed over the wire.
Any help in this regard would be greatly appreciated!
Thanks....
You must throw an exception of type DataServiceException.