Array instead of List in WCF Service Proxy Generated using svcutil.exe - arrays

I have a ServiceContract,
using System.Collections.Generic;
using System.ServiceModel;
namespace MainModule.Sub.Communication
{
[ServiceContract]
public interface IWebMethod
{
[OperationContract(IsOneWay = false)]
bool InvokeAlert(List<int> userIds);
[OperationContract(IsOneWay = false, Name = "InvokeAlertByMainID")]
bool InvokeAlert(List<int> userIds, int mainId);
[OperationContract(IsOneWay = true)]
void DeletePopupNotifications(System.Data.DataSet deletedNotifications);
}
}
I used below command to generate proxy (I have to do this using command-line not via Add Service Reference.
SvcUtil.exe http://localhost/MainCommunicationServer/wm /ct:System.Collections.Generic.List`1 /out:HTTPRouterServerProxy.cs
Even I added the ct switch (collectionType) the proxy is Generating it as Array (int[]). How can I do that without using Add Service Reference window in VS

If I remember correctly, the /ct switch may not have any effect (in some circumstances?) on OperationContract-level collections. Try using a wrapper DataContract type, e.g. bool InvokeAlert(InvokeAlertRequest r); where InvokeAlertRequest will be a [DataContract] type containing one [DataMember] List<int> userIds;

The /ct switch stops working if SvcUtil fails to create a proxy that uses the DataContractSerializer and uses the XmlSerializer instead.
This is just a guess but I suspect that System.Data.DataSet might be causing this.

Related

Azure Logic Apps- How to implement long-running tasks via Durable Functions, via the polling action pattern

I have an azure function that takes in these parameters (source container, source filename, destination folder, and destination container) and unzips the source filename in the folder in the destination container. There are several actions in the Logic App workflow following the Azure Unzip action that are not completed because the Logic app would timeout after completing the unzipping due to the file size. So Azure function was revamped to be a durable function and I am trying to implement it into my Logic app via the polling action. According to this site, https://medium.com/#jeffhollan/calling-long-running-functions-from-logic-apps-6d7ba5044701, I can use the built-in Azure Functions action but I have no idea what the actual workflow should look like. I am looking for a step by step graphic demonstration on how to implement the durable function via the polling action pattern in my Logic App like depicted on this page, https://yourazurecoach.com/2018/08/19/perform-long-running-logic-apps-tasks-with-durable-functions/ (which shows how to implement it via the webhook action pattern). Any help would be greatly appreciated. Thanks in advance.
After you executing built-in Azure Functions in Logic APP, you will get 202 status code. Then you can handle your business in QueueTrigger.
You can have a look at this sample:
using System.IO;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs.Host;
using Newtonsoft.Json;
using System.Threading;
using System.Net.Http;
using System;
namespace HttpToQueueWebhook
{
public static class HttpTrigger
{
[FunctionName("HttpTrigger")]
public static IActionResult Run(
[HttpTrigger(AuthorizationLevel.Function, "post")]HttpRequest req,
TraceWriter log,
[Queue("process")]out ProcessRequest process)
{
log.Info("Webhook request from Logic Apps received.");
string requestBody = new StreamReader(req.Body).ReadToEnd();
dynamic data = JsonConvert.DeserializeObject(requestBody);
string callbackUrl = data?.callbackUrl;
//This will drop a message in a queue that QueueTrigger will pick up
process = new ProcessRequest { callbackUrl = callbackUrl, data = "some data" };
return new AcceptedResult();
}
public static HttpClient client = new HttpClient();
/// <summary>
/// Queue trigger function to pick up item and do long work. Will then invoke
/// the callback URL to have logic app continue
/// </summary>
[FunctionName("QueueTrigger")]
public static void Run([QueueTrigger("process")]ProcessRequest item, TraceWriter log)
{
log.Info($"C# Queue trigger function processed: {item.data}");
//Thread.Sleep(TimeSpan.FromMinutes(3));
//ProcessResponse result = new ProcessResponse { data = "some result data" };
//handle your business here.
client.PostAsJsonAsync<ProcessResponse>(item.callbackUrl, result);
}
}
public class ProcessRequest
{
public string callbackUrl { get; set; }
public string data { get; set; }
}
public class ProcessResponse
{
public string data { get; set; }
}
}
More details, you can refer to this answer logic apps web hook to chalkboard API timeout error.

How do I call custom methods in a Wcf Data Service from a Silverlight application?

I have the following Wcf Data Service:
public class WcfDataService : DataService<WcfDataServiceContext>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
config.UseVerboseErrors = true;
}
[WebGet]
public IQueryable<Person> GetPeopleByName(string name)
{
WcfDataServiceContext context = this.CurrentDataSource;
var match = from p in context.People
where p.FirstName == name
select p;
return match;
}
I can access the custom method from the browser like this:
http://127.0.0.1:8080/DataService/WcfDataService.svc/GetPeopleByName?name='Daniel'
How can I call that method and get that list of Person from a Silverlight application?
I'm using Visual Studio 2012, Silverlight 5, .NET Framework 4.0.
As far as I remember whe using Silverlight you cannot connect to a different server than the one the Silverlight app came from so you would just use a relative Uri. If you would like to use WCF Data Services client you can take a look here: http://forums.silverlight.net/t/208481.aspx - there is a code snippet that shows it. However AFAIK WCF Data Services client does not support Service Operation so you may need to use XmlReader to be able to query and parse the response of the GetPeopleByName function.
I did it before I can share.Service Reference your domain:8080/DataService/WcfDataService.svc then
For Person object use [DataContract] attribute for properties of Peson use [global::System.Runtime.Serialization.DataMemberAttribute()] By this way you say Serialize and create proxies to Bus side. Notice this attributes because it really works!
//Here is the interface attributes are important
namespace AHBSBus.Web.Services
{
[ServiceContract]
public interface IChatService
{
[OperationContract]
bool LogIn(Guid userID,Guid roomID);
[OperationContract]
bool LogOut(Guid userID,Guid roomID);
[OperationContract]
IEnumerable<VW_CHATUSERDETAIL> GetLatestMessages(Guid userID,Guid roomID,Guid lastSyncMessageID);
[OperationContract]
bool SendMessage(Guid fromID, Guid roomID, Guid toID, string message);
[OperationContract]
IEnumerable<ChatUser> GetLoggedInUsers(Guid roomID);
[OperationContract]
bool IsLogin(Guid roomID,Guid userID);
}
}
//Implementation of service
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public partial class ChatService:IChatService
{
//Here goes
}

Using the same class library in windows application and web service

I working with:
Class Library: Model.dll
using System;
using System.Collections.Generic;
using System.Text;
namespace root
{
public class Customer
{
private int _Id;
public int Id
{
get { return _Id; }
set { _Id = value; }
}
private string _Name;
public string Name
{
get { return _Name; }
set { _Name = value; }
}
}
}
ASP.NET Web Service with reference to Model.dll so i can use in web method:
[WebMethod]
public string HelloWorld(root.Customer customer) {
return "Hello World";
}
Windows Application with reference to both Model.dll and Web Service (1).
root.Customer newCustomer = new Customer();
newCustomer.Id = 1;
newCustomer.Name = "Name";
ws.Service ws = new root.ws.Service();
ws.HelloWorld(newCustomer);
^ problem here
Error: Argument '1': cannot convert from 'root.Customer' to 'root.ws.Customer'
(1) Right click -> And Web Reference -> Web services in this solution -> Click Service.asmx ->
Enter Web reference name: ws -> Click Add reference
Updated: I can change line in generated Reference.cs file from
public string HelloWorld(Customer customer)
to
public string HelloWorld(root.Customer customer)
So function will be looking for real model instead of proxy object, but is not real answer.
I don't event think about editing this file after each web reference update.
How to force this for using real model?
I am afraid that reusing types in automatically generated ASMX proxies is impossible.
There are three options.
1) write your own code generator that will act like the wsdl.exe i.e. build a proxy of your web service but reusing your specified types
(rather difficult)
2) write your own code rewriter that will rewrite proxies generated automatically to use your own types. You'd invoke such rewriter each time after you build up your reference to the web service
(still tedious)
3) switch to WCF web services. a WCF service on a basicHttpBinding is semantically equivalent to a ASMX web service (uses the same communication protocol based on http + soap) but the WCF service metadata contain more information about types so that the proxy generator is able to "reuse types from referenced assemblies".
(suggested approach)
If you switch away from asmx and start using WCF's svc model, you can share a library between the server and client without much fuss at all. If that is an option, there are plenty of resources to help you out with WCF online.

How to initialize local fields of a WCF proxy class on deserialization

In my Silverlight client I have a partial class created by setting a WCF reference. I've extended this class adding a few RelayCommand properties. I need to initialize these properties which I would normally do in the constructor. However it seems that the constructor is not being called, which I believe is a result of of VTS However I'm also unsuccessful in using the OnDeserialized attribute.
What is the prescribed way to initialize client side data members of a WCF class.
I've created a sample project and everything works as expected. If this code doesn't help - post your data contract and client code.
namespace SilverlightApplication3.ServiceReference1
{
public partial class SomeModel
{
public string ExtendedProperty { get; set; }
[OnDeserializing]
public void OnDeserializingMethod(StreamingContext context)
{
this.ExtendedProperty = "Ok";
}
}
}
Service method call:
var proxy = new ServiceReference1.Service1Client();
proxy.DoWorkCompleted += (s,e) => Debug.WriteLine(e.Result.ExtendedProperty); //Ok
proxy.DoWorkAsync();

Issue intercepting property in Silverlight application

I am using Ninject as DI container in a Silverlight application. Now I am extending the application to support interception and started integrating DynamicProxy2 extension for Ninject. I am trying to intercept call to properties on a ViewModel and ending up getting following exception:
“Attempt to access the method failed: System.Reflection.Emit.DynamicMethod..ctor(System.String, System.Type, System.Type[], System.Reflection.Module, Boolean)”
This exception is thrown when invocation.Proceed() method is called. I tried two implementations of the interceptor and they both fail
public class NotifyPropertyChangedInterceptor: SimpleInterceptor
{
protected override void AfterInvoke(IInvocation invocation)
{
var model = (IAutoNotifyPropertyChanged)invocation.Request.Proxy;
model.OnPropertyChanged(invocation.Request.Method.Name.Substring("set_".Length));
}
}
public class NotifyPropertyChangedInterceptor: IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
var model = (IAutoNotifyPropertyChanged)invocation.Request.Proxy;
model.OnPropertyChanged(invocation.Request.Method.Name.Substring("set_".Length));
}
}
I want to call OnPropertyChanged method on the ViewModel when property value is set.
I am using Attribute based interception.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class NotifyPropertyChangedAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
if(request.Method.Name.StartsWith("set_"))
return request.Context.Kernel.Get<NotifyPropertyChangedInterceptor>();
return null;
}
}
I tested the implementation with a Console Application and it works alright.
I also noted in Console Application as long as I had Ninject.Extensions.Interception.DynamicProxy2.dll in same folder as Ninject.dll I did not have to explicitly load DynamicProxy2Module into the Kernel, where as I had to explicitly load it for Silverlight application as follows:
IKernel kernel = new StandardKernel(new DIModules(), new DynamicProxy2Module());
Could someone please help? Thanks
Reflection can be really tricky in silverlight because of security issues.
Check Gabe's answer for this question, it's the same problem.
The good news is that you can achieve the same functionality you want using dynamic instead of proxies. Just extend your ViewModel from DynamicObject and override the TrySetMember method.
I hope it helps :)

Resources