System.Threading.Tasks.Task - cannot be serialized because it does not have a parameterless constructor. - wcf

I am currently using the WCF Web API and it is working great with synchronous tasks.
However, when I try and implement asynchronous operations using Task/Task like so:
[WebGet(UriTemplate = "landmark")]
Task<IEnumerable<Closest>> GetLandmarkAsync(float latitude, float longtitude)
{
return Task.Factory.StartNew(() => CalculateClosestThing(latitude, longtitude));
}
I am getting this error:
System.Threading.Tasks.Task`1[System.Collections.Generic.IEnumerable`1[ContentRepository.Data.Entities.Closest]] cannot be serialized because it does not have a parameterless constructor.
Now, the first thing I did was check the Closest Class and add a parameterless constructor like so:
public class Closest
{
public Closest() { }
public double Distance { get; set; }
public string Name { get; set; }
}
But I'm still getting the same error. I've tried everything and clearly there is a parameterless constructor on the class. Has anyone ever experienced this? Any ideas?

Ensure you new up a WebApiConfiguration obj (derived from HttpConfiguration) and set it as the default Http configuration with a call to routes.SetDefaultHttpConfiguration() in the host (I'm using an MVC host).
I had the same problem as you before I switched from HttpConfiguration to WebApiConfiguration.
For more details see here.

Give these a read:
http://arbel.net/2011/06/04/wcf-tasks/
http://msdn.microsoft.com/en-us/library/ms730059.aspx
http://www.dotnetcurry.com/ShowArticle.aspx?ID=237

Related

Exception when adding new method in a working Service using gRPC-Web and protobuf-net

I am getting the following exception:
Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: The type initializer for 'DefaultProxyCache1' threw an exception. System.TypeInitializationException: The type initializer for 'DefaultProxyCache1' threw an exception. ---> System.ArgumentException: Invalid generic arguments
Parameter name: typeArguments
at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.MakeGenericMethod_impl(System.Reflection.RuntimeMethodInfo,System.Type[])
at System.Reflection.RuntimeMethodInfo.MakeGenericMethod (System.Type[] methodInstantiation) <0x342def8 + 0x000d6> in :0
at ProtoBuf.Grpc.Internal.ContractOperation.TryGetClientHelper () [0x0001b] in //src/protobuf-net.Grpc/Internal/ContractOperation.cs:291
at ProtoBuf.Grpc.Internal.ProxyEmitter.EmitFactory[TService] (ProtoBuf.Grpc.Configuration.BinderConfiguration binderConfig) [0x00477] in //src/protobuf-net.Grpc/Internal/ProxyEmitter.cs:238
at ProtoBuf.Grpc.Internal.ProxyEmitter.CreateFactory[TService] (ProtoBuf.Grpc.Configuration.BinderConfiguration binderConfig) [0x0006d] in //src/protobuf-net.Grpc/Internal/ProxyEmitter.cs:123
at ProtoBuf.Grpc.Configuration.ClientFactory+DefaultProxyCache`1[TService]..cctor () [0x00000] in //src/protobuf-net.Grpc/Configuration/ClientFactory.cs:81
My project uses gRPC-Web, Blazor web assembly and protobuf-net
This is my service contract:
[ServiceContract(Name = "Services.Customer")]
public interface ICustomerService
{
ValueTask<Customer> CreateCustomer(Customer customerDTO);
ValueTask<CustomerResultSet> GetCustomers();
}
The implementation is:
public class CustomerService : ICustomerService
{
private readonly CustomerUseCases customerLogic;
public CustomerService(CustomerUseCases customerLogic)
{
this.customerLogic = customerLogic;
}
public async ValueTask<Customer> CreateCustomer(Customer customerDTO)
{
var result = await customerLogic.CreateCustomer(customerDTO);
return customerDTO;
}
public async ValueTask<CustomerResultSet> GetCustomers()
{
CustomerResultSet result = new CustomerResultSet { Customers = await customerLogic.GetCustomer() };
return result;
}
}
As for the Datacontracts:
[DataContract]
public class CustomerResultSet
{
[DataMember(Order = 1)]
public IEnumerable<Customer> Customers { get; set; }
}
And,
[DataContract]
public partial class Customer
{
[DataMember(Order = 1)]
public int CustomerId { get; set; }
[DataMember(Order = 2)]
public string CustomerName { get; set; }
}
Before I was returning a List of customers in the service but I realize I needed a class to model the message in order to protobuf-net be able to serialize that is why CustomerResultSet. Still, it is not working.
Any help much appreciated
That is... odd. I can't repro it here, so I'm guessing it is something specific to Blazor. I've checked what the code does in the "regular" frameworks, and at least for me it seems to do the right things - using UnaryValueTaskAsync<Customer, Customer>() and UnaryValueTaskAsync<Empty, CustomerResultSet>(), which is what I would expect. I've improved the exception handling in that code path, to at least give us a clue what it is trying to do, so my suggestion is:
update to protobuf-net.Grpc version >= 1.0.119 (I'll get it deployed as soon as CI finishes)
retry, and let me know exactly what it says now
Alternatively, if you have a minimal repro including the blazor bits on, say, a GitHub repo, I can happily take a look there.
(tip: I try to keep an eye on both Stack Overflow and GitHub, but GitHub is probably more appropriate for this kind of question - I'd happily say that this is a bug, so: https://github.com/protobuf-net/protobuf-net.Grpc/issues)
I was having a similar problem.
System.InvalidOperationException: Error obtaining client-helper 'UnaryValueTaskAsync' (from: 'System.Guid', to: 'Test.DTO.OpResult'): Invalid generic arguments
My entire ServiceContract on that service stopped working. This happened after I added
ValueTask ChangeCompany(Guid companyGuid);
I changed it to
ValueTask ChangeCompany(string companyGuid);
And that got it working again. The error was a bit confusing since i wasn't using ChangeCompany, but like a said, not calls were working.

Automapper unmaped property found

Hi guys I have found a very strange thing and I want to ask you about that.
I am using AutoMaper in my .dotnet core Web Api project. And during mapping i get the AutoMapperConfigurationException.
Here is a reference I am currently using:
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="5.0.1" />
I have a Blog entity class :
public class BlogEntity
{
public string Title { get; set; }
public int BlogEntityId { get; set; }
public List<Post> Posts { get; set; }
}
And my DTO class which I am using to create a new blank blog entity:
public class BlogCreateDto
{
public string Title { get; set; }
}
Here is my mapper profile:
public class BlogMappingProfile : Profile
{
public BlogMappingProfile()
{
CreateMap<BlogCreateDto,BlogEntity>();
}
}
Here is a line that i used in Startup.cs to set up automapper
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddAutoMapper();
....
Here is a message that i get in exception:
Unmapped members were found. Review the types and members below.\nAdd
a custom mapping expression, ignore, add a custom resolver, or modify
the source/destination type\nFor no matching constructor, add a no-arg
ctor, add optional arguments, or map all of the constructor
parameters\n==========================================================\r\nAutoMapper created this type map for you, but your types cannot be mapped using
the current configuration.
I tried a lot of things, Ignore of members, constructors, inheritance etc and none of them didn't work. I resolved it by adding configuration in Startup.cs and adding my automapper profile by hand like this:
services.AddAutoMapper(cfg => cfg.AddProfile(new BlogMappingProfile()));
It is working but still i have a confusion about that i miss something and didn't do it in properly way. What I am doing wrong ? Or maybe I miss something in configuration?
You have to provide the assemblies or the assembly, where your profiles are located. The extension is using assembly-scanning to find given types to register. If your profiles are in the same project as your startup class, you can do the following
services.AddAutoMapper(typeof(Startup).Assembly);
You will also need that to automatically register all other AutoMapper types like IValueResolver<,,> and ITypeConverter<,> for instance.
You can find the registration process of that extension here.
In my case, I've forgotten to add the Profile file into the AutoMapperConfig class
something like this
public static void Configure(MapperConfigurationExpression config)
{
config.AddProfile<SettingsProfile>();
}

how to access endpoint configuration in a custom NServiceBus profile handler

I'm migrating code from NSBv4 to NSBv5 (5.2.12 to be exact) and I have a custom profile implementation:
public class MyProfileHandler : IHandleProfile<PerformanceCounters>
{
public MyProfileHandler()
{
}
public void ProfileActivated(BusConfiguration config)
{
// I need to do something based on endpoint configuration, e.g. endpoint name
// this used to work in NSBv4:
// var endpointName = Configure.EndpointName;
}
}
How can I access endpoint configuration here?
I'm hosting this app using NServiceBus.Host (v6.0.0 if it matters) and this is where the IHandleProfile<T> interface comes from.
BusConfiguration is a configuration builder and it seems it's not possible to read anything useful from it. I tried to inject an instance of Configure to the constructor of my profile handler, but then it crashes - NSB needs the handler to have a parameterless constructor.
Implementing IWantTheEndpointConfig is not an option as well, as it is deprecated in v5 and it causes a compilation error. Its obsolete error message states:
IHandleProfile is now passed an instance of Configure
(which would be perfect for my case), but this is not true as far as I can tell (there is no Configure passed to ProfileActivated() and I can't see how I can inject it).
Is my only option to reimplement the profile handler using a completely different approach, or am I missing something?
NServiceBus.Core has an issue how it sets the endpoint name (and unfortunately also the endpoint version) on the BusConfiguration. The set endpoint name is added to the settings dictionary too late. You can work around that issue by doing the following:
public class EndpointConfig : IConfigureThisEndpoint
{
public void Customize(BusConfiguration configuration)
{
var customConfig = new EndpointConfiguration
{
EndpointName = "YourEndpointName",
};
configuration.EndpointName(customConfig.EndpointName);
configuration.GetSettings().Set<EndpointConfiguration>(customConfig);
}
}
public class EndpointConfiguration
{
public string EndpointName { get; set; }
}
BusConfiguration is essentially a dictionary on steroids. If you want to get access to what has been set in the BusConfiguration in the profile handler you can do the following (i.ex. get the endpoint name):
public class MyProfileHandler : IHandleProfile<PerformanceCounters>
{
public void ProfileActivated(BusConfiguration config)
{
var customConfig = config.GetSettings().Get<EndpointConfiguration>();
var endpointName = customConfig.EndpointName;
}
}
In the normal NServiceBus Host the interface offers only the one parameter, BusConfiguration. On Azure the interface offers two methods, where one actually has the Configure object.

WCF - call method from service implementation

What I'm trying to do is the following:
1) I have the following WCF service contract:
[ServiceContract]
public interface IUploadService
{
[OperationContract]
ServiceData Upload(Request request);
}
[DataContract]
public class Request
{
[DataMember]
public long AbnNumber;
[DataMember]
public string Email;
}
2) This contract is implemented like this.
public class UploadService : IUploadService
{
public bool Upload(Request request)
{
// Some code
}
}
In the "Some code" section I would like to call a validation class to validate the clients request, so something like this:
var result = validation.ValidateRequest(request);
So my question is: Is it a bad idea to create an instance of my validation class inside the Upload method? Like this:
public class UploadService : IUploadService
{
public bool Upload(Request request)
{
var validation = new Validation();
var result = validation.ValidateRequest(request);
}
}
I know you can get around this by creating a constructor but as far as I know you can't create a constructor inside a WCF service implementation class, or am I wrong?
I'm new to WCF so if I'm totally heading the wrong direction please let me know.
Thanks
Personally I like as little as possible in my service methods. I would have a separate project to handle the Upload. This then allows you to reuse this code more easily, and to test the functionality without creating the service.
As to whether you should create your Validation like this it really depends on what it does, but generally I would make sure the Validation class implements an interface containing ValidateRequest(Request) and then inject that. You can then mock it in your tests if you need to.
So your service code would look like
public class UploadService : IUploadService
{
private readonly IUploadHandler _uploadHandler;
public UploadService(IUploadHandler uploadHandler)
{
_uploadHandler = uploadHandler;
}
public bool Upload(Request request)
{
//would possibly do some mapping here to create a different type of object to pass to the handler
_uploadHandler.Upload(request);
}
}
and the handler in a different project would look like
public class UploadHandler : IUploadHandler
{
private readonly IValidation _validator;
public UploadHandler(IValidation validator)
{
_validator = validator;
}
public bool Upload(Request request)
{
return _validator.ValidateRequest(request);
}
}
So my question is: Is it a bad idea to create an instance of my validation class inside the Upload method?
It comes down to whether you will be using Singleton or Per Call services. Usually it is better to have new instance of Service created for every request, and in that case it is OK to create all instances in your operation.
Interesting discussion on this topic Should WCF service typically be singleton or not?
If you decide to not to create Validation class for each then request there are two options:
Make it singleton
Create custom ServiceHostFactory for your service and initialize your Service in it (with constructor). Useful links on this topic:Extending Hosting Using ServiceHostFactory, Integrating StructureMap with WCF

WCF Service not showing my functions

I have written following code, but only first method in service shows up in client side but rest of two doesn't :(
any one guide me what could be the issue?
ServiceInterface:
[ServiceContract]
public interface IService1
{
[OperationContract]
claimantResponse SaveClaimant(claimant claimant);
[OperationContract]
claimantResponse RenewExpiry(claimantMin claimantMin);
[OperationContract]
claimantResponse getAccessCode(claimantMin claimantMin);
}
ServiceImplementation:
public class Service1 : IService1
{
public claimantResponse SaveClaimant(claimant claimant)
{
return new claimantBLL().SaveClaimant(claimant);
}
public claimantResponse RenewExpiry(claimantMin claimantMin)
{
return new claimantBLL().RenewExpiry(claimantMin);
}
public claimantResponse getAccessCode(claimantMin claimantMin)
{
return new claimantBLL().getAccessCode(claimantMin);
}
}
Data:
[DataMember]
public class claimantResponse
{
private List<string> _ErrorMessage = new List<string>();
[DataMember]
public List<string> ErrorMessage
{
get { return _ErrorMessage; }
set { _ErrorMessage = value; }
}
private List<int> _ErrorCode = new List<int>();
[DataMember]
public List<int> ErrorCode
{
get { return _ErrorCode; }
set { _ErrorCode = value; }
}
[DataMember]
public String FormStatus { get; set; }
[DataMember]
public DateTime ExaminationDate { get; set; }
[DataMember]
public String AccessCode { get; set; }
[DataMember]
public String Status { get; set; }
[DataMember]
public string temp2 { get; set; }
}
It shows two strange methods getdata and getdataobject instead of my own methods.. :(
Any help would be appreciated.
The code that you have posted will not compile. Due to the data member attribute on the class.
If you then press "run anyway" (cannot remember the exact text, but something close to that). Then it will run the last version of the code that compiled. The method names that you are seeing could have been in the original template that you used to create the service.
I resolved this problem by simply restarting Visual Studio 2012 :-)
My version of the problem was that renaming methods and removing the OperationContract attribute off an interface did not make a change to the methods I saw when I ran WCF test client. I even commented out a method and Visual Studio ran the debugger for that method! I restarted Visual Studio and it was back to normal.
I got solution to this problem and posting here so might help any body else with same scenario:
1) Removing [DataMember] attribute from the class and properties.
2) creating a new WCF simple service and putting same code worked.
i did remove datamember attribute from the old service but it was not working, so i assume my service was got corrupted because it was not showing any new method that a new service did :(
3) web.cofig would remain same from the time you you created sample of wcf and no change is required in this case.
Thank you!
So I had the same issue and could not see any new method that added regardless of Datacontract
first thing you need to have to expose your methods will be Data Annotation (attribute) OperationContract above your method inside the interface like the example below:
[ServiceContract]
public interface IService
{
[OperationContract]
Student_Identification GetStudentIdentification(int StudentId);
}
This was my first problem but I still couldn't see it, so I decide to update my service reference in the app where its being referenced
When I clicked Update Service Reference, an error message displayed saying it was unable to connect to server. In my case, the service was pointing to a different server. But I needed to point to my local computer, so I clicked Configure Service Reference
An there was my problem, the client address was set to a different url and not my local dev machine. I tried adding a host entry in my host file with the existing url the service was using and that still didn't fix my issue. So I went ahead and opened IIS since I have this project setup locally. selected my site, right clicked and selected Edit Bindings...
Click add and add the url address in the service and dont forgot to add it to you host file just in case. commonly located here -> C:\Windows\System32\drivers\etc
go back to the app thats referencing the service, right click service reference and select update service reference. This worked for me hopefully this helps someone on their journey.