在Xamarin跨平台应用程序中使用WCF服务

6
我创建了一个WCF服务,可以从SQL数据库检索数据,并将数据更新和修改回SQL数据库。我正在尝试从Xamarin for Android和Xamarin for iOS调用WCF方法。我搜索了很多例子,想知道如何通过Xamarin for Android和Xamarin for iOS调用WCF服务的PUT和POST方法,但没有成功。下面是参考的WCF代码...我甚至创建了Web API,但所有消费Web API的示例和教程都是关于如何调用GET方法的。我没有看到任何参考文档,可以展示如何跨平台调用WCF或Web API的PUT或Post方法。我已经通过Fiddler测试了WCF服务并且工作正常。下一步应该怎么做呢?我使用SlsvcUtil.exe创建了这个Web服务的代理,就像Xamarin文档中提到的那样。有人能发一个Xamarin.Android的例子来调用下面WCF服务的更新或删除方法吗?非常需要帮助。服务包含webHttp绑定。
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Runtime.Serialization; 
using System.ServiceModel; 
using System.ServiceModel.Web; 
using System.Text;

public class Service1 : IService1 
{ 
    public List GetDeptsList() 
    { 
        using (DeptDBEntities entities = new DeptDBEntities()) 
        { 
            return entities.Depts.ToList(); 
        } 
    }

    public Dept GetDeptByID(string no)
    {
        try
        {
            int deptId = Convert.ToInt32(no);

            using (DeptDBEntities entities = new DeptDBEntities())
            {
                return entities.Depts.SingleOrDefault(dept => dept.no == deptId);
            }
        }
        catch
        {
            throw new FaultException("Something went wrong");
        }
    }

    public void AddDept(string name)
    {
        using (DeptDBEntities entities = new DeptDBEntities())
        {
            Dept dept = new Dept { name = name };
            entities.Depts.Add(dept);
            entities.SaveChanges();
        }
    }

    public void UpdateDept(string no, string name)
    {
        try
        {
            int deptId = Convert.ToInt32(no);

            using (DeptDBEntities entities = new DeptDBEntities())
            {
                Dept dept = entities.Depts.SingleOrDefault(b => b.no == deptId);
                dept.name = name;
                entities.SaveChanges();
            }
        }
        catch(Exception e)
        {
            throw new FaultException(e.Message);

        }
    }

    public void DeleteDept(string no)
    {
        try
        {
            int deptId = Convert.ToInt32(no);

            using (DeptAppDBEntities entities = new DeptAppDBEntities())
            {
                Dept dept = entities.Depts.SingleOrDefault(b => b.no == deptId);
                entities.Depts.Remove(dept);
                entities.SaveChanges();
            }
        }
        catch
        {
            throw new FaultException("Something went wrong");
        }
    }

}

web.config

   <?xml version="1.0"?>
      <configuration>
      <configSections>
       <section name="entityFramework"   type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
     </configSections>
     <system.web>
     <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
      </assemblies>
      </compilation>
      <pages controlRenderingCompatibilityVersion="4.0"/>
      </system.web>
      <system.serviceModel>
                 <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
      </behaviors>
      <services>
      <service name="WcfWithJsonP.Service1" behaviorConfiguration="restfulBehavior">
        <endpoint address="" behaviorConfiguration="webBehavior" binding="webHttpBinding" bindingConfiguration="" contract="WcfWithJsonP.IService1"/>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost/Service1"/>
          </baseAddresses>
        </host>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
       </services>
      <behaviors>
      <endpointBehaviors>
        <behavior name="webBehavior">
          <webHttp defaultOutgoingResponseFormat="Json"/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="restfulBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
      </behaviors>
      <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
      </system.serviceModel>
     <system.webServer>
     <modules runAllManagedModulesForAllRequests="true"/>
        <directoryBrowse enabled="true"/>
     </system.webServer>
     <entityFramework>
     <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory,   EntityFramework">
      <parameters>
        <parameter value="v12.0"/>
      </parameters>
     </defaultConnectionFactory>
     </entityFramework>
    </configuration

>

主要的axml文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:minWidth="25px"
    android:minHeight="25px">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="134.1dp"
        android:layout_height="fill_parent"
        android:minWidth="25px"
        android:minHeight="25px">
        <TextView
            android:text="Enter No:"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:layout_width="163.4dp"
            android:layout_height="wrap_content"
            android:id="@+id/No"
            android:layout_marginBottom="27.5dp"
            android:layout_marginTop="0.0dp"
            android:layout_marginLeft="5dp" />
        <TextView
            android:text="Enter name:"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:layout_width="252.7dp"
            android:layout_height="wrap_content"
            android:id="@+id/Name"
            android:layout_marginBottom="27.5dp"
            android:layout_marginTop="0.0dp"
            android:layout_marginLeft="5dp"
            android:enabled="false"
            android:visibility="invisible" />
    </LinearLayout>
    <Button
        android:id="@+id/Get"
        android:layout_width="fill_parent"
        android:layout_height="36.6dp"
        android:text="Get" />
    <Button
        android:id="@+id/ADD"
        android:layout_width="fill_parent"
        android:layout_height="36.6dp"
        android:text="ADD" />
    <Button
        android:id="@+id/Update"
        android:layout_width="fill_parent"
        android:layout_height="36.6dp"
        android:text="Update" />
    <Button
        android:id="@+id/Delete"
        android:layout_width="fill_parent"
        android:layout_height="36.6dp"
        android:text="Delete" />
    <TextView
        android:text=""
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/ValueNo"
        android:layout_marginBottom="27.5dp"
        android:layout_marginTop="0.0dp"
        android:background="@android:color/holo_purple" />
    <TextView
        android:text=""
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/ValueName"
        android:layout_marginBottom="27.5dp"
        android:layout_marginTop="0.0dp"
        android:background="@android:color/holo_purple" />
</LinearLayout>

我已经添加了config.file,并且正在使用Xamarin创建简单的Android项目来调用此服务。 - user2897967
是的,我创建了代理并将其添加到我的项目中。基本上,我希望在单击按钮时添加或删除记录。通过WCF服务将输入框中输入的值添加到数据库中,当单击ADD按钮时。如果单击Get按钮,则必须从WCF服务检索输入的值,即GetDeptById,并在文本框中显示。没有文本框可以显示no,名称文本框必须显示name。 - user2897967
太好了。现在你只需要在Xamarin.Android项目中创建一些按钮和点击事件处理程序。在事件处理程序或类级别上,创建一个新的服务客户端实例,该实例在代理中定义,并调用AddDept或DeleteDept方法。代理的生成基于代理创建的服务为您创建这些方法。 - jensendp
我在这里添加我的XML。但不确定如何开始或添加什么。 - user2897967
我将创建一个带有示例的代码片段。 - jensendp
显示剩余2条评论
2个回答

0
这是一个简单的代码片段,可用作指南:
//first at the class level, create a private variable for the client.
private Service1Client _client;
private Button _addButon;
private TextView _txtDeptName;

//Initialize the _client in the OnCreate() method.
protected override void OnCreate(Bundle bundle)
{
     base.OnCreate(bundle);

     var endpoint = new EndpointAddress("http://<ipAddress:port>/Service1.svc");

     var binding = new BasicHttpBinding{
        Name = "basicHttpBinding",
        MaxBufferSize = 2147483647,
        MaxReceivedMessageSize = 2147483647
    };

    TimeSpan timeout = new TimeSpan(0, 0, 30);
    binding.SendTimeout = timeout;
    binding.OpenTimeout = timeout;
    binding.ReceiveTimeout = timeout;

    _client = new Service1Client(binding, endpoint);
    _client.AddDeptCompleted += ClientAddDeptCompleted;

    _addButton = FindViewById<Button>(Android.Resources.Id.Add);
    _addbutton.Click += AddButton_Clicked;

    _txtDeptName = FindViewbyId<TextView>(Android.Resources.Id.Name);
}

//Then within the event handlers, do something like this
public void AddButton_Clicked(object sender, EventArgs e)
{
     _client.AddDeptAsync(_txtDeptName.Text);
}

//Handle the request completed event.
private void ClientAddDeptCompleted(object sender, AddDeptCompletedEventArgs addDeptCompletedEventArgs)
{
     //TODO: Something with the notification that the request has completed.
}

你应该能够类似地跟随其他按钮和服务调用的模式。如果我打错了一些字,请原谅。我是根据一些记忆和Xamarin网站上的WCF指令来完成这个。

谢谢帮忙!但是我们需要再次添加绑定吗,因为我的配置文件包含webHttpBinding。而且我们需要将文本框中的值分配给ADD方法的函数参数。 - user2897967
web.config文件与WCF服务一起存在。我通常不会以这种方式生成代理,因此我不确定代理中包含哪些绑定信息。您可以尝试在不显式创建新绑定的情况下进行操作。另外,我更新了我的帖子,并添加了一些代码来从TextView获取部门名称。 - jensendp
再次感谢您的帮助。我已经按照文档中提到的方向创建了代理。是否有其他创建代理的方法?由于您使用Xamarin创建了移动应用程序,您建议使用WCF从SQL生成数据还是使用Web API?我也创建了Web API,但不确定如何在Xamarin中使用它。没有适当的WCF或Web API示例...我们可以使用Xamarin编辑SQL数据库。 - user2897967
1
这是创建代理的可接受方式。我通常不使用Xamarin中的WCF服务,但在许多其他桌面或Web应用程序中使用WCF服务。从Xamarin中,我倾向于使用Web Api Web服务,在其中使用HttpClient类创建HTTP请求与它们进行交互。看一下那个类,它相当容易理解。 - jensendp
我不确定我们是否需要为Web API创建自定义媒体格式化程序。您能否分享一个示例,说明如何在单击事件上触发获取或修改SQL数据的方法。我已经创建了Web API,但不确定如何在单击事件上调用方法。我们需要创建代理还是如何添加引用? - user2897967
显示剩余3条评论

0

首先,您必须将服务添加到您的项目中。您可以使用以下命令完成:

Cd C:\Program Files (x86)\Microsoft SDKs\Silverlight\v5.0\Tools\ SlSvcUtil.exe http://localhost:2323/HisDashboardService/ProfilerService.svc /directory:"C:\Folder"

然后,将其添加到创建的项目文件中。 要使用已添加的服务,必须按照以下步骤进行操作。

public class ServiceAccessor
{
    static string serviceUrl = "http://172.16.12.17:7698/HisDashboardService/";
    public static readonly EndpointAddress ProfilerServiceEndPoint = new EndpointAddress(serviceUrl + "ProfilerService.svc");

    private ProfilerServiceClient _profilerServiceClient;

    private static ServiceAccessor _instanceServiceAccessor;
    public static ServiceAccessor Instance
    {
        get { return _instanceServiceAccessor ?? (_instanceServiceAccessor = new ServiceAccessor()); }
    }

    ServiceAccessor()
    {
        InitializeServiceClient();
    }

    private void InitializeServiceClient()
    {
        BasicHttpBinding binding = CreateBasicHttp();

        #region ProfilerService
        _profilerServiceClient = new ProfilerServiceClient(binding, ProfilerServiceEndPoint);
        #endregion ProfilerService
    }

    private static BasicHttpBinding CreateBasicHttp()
    {
        BasicHttpBinding binding = new BasicHttpBinding
        {
            Name = "basicHttpBinding",
            MaxBufferSize = 2147483647,
            MaxReceivedMessageSize = 2147483647
        };
        TimeSpan timeout = new TimeSpan(1, 0, 0);
        binding.SendTimeout = timeout;
        binding.OpenTimeout = timeout;
        binding.ReceiveTimeout = timeout;
        return binding;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接