Is it possible to use RealProxy to expose class interfaces over Remoting without MarshalByRefObject? - remoting

Is it possible to make a RealProxy that looks like this:
public InterfaceProxy(object instance, params Type[] interfaces)
and can expose all these interfaces over remoting, delegating calls to instance, even if an instance is not a MarshalByRefObject?
Currently I am having a problem where proxy receives a call to InitializeLifetimeService, and whatever I return from it (including null), I am always getting a following exception:
System.InvalidCastException:Return argument has an invalid type
at System.Runtime.Remoting.Proxies.RealProxy.ValidateReturnArg(Object arg, Type paramType)
at System.Runtime.Remoting.Proxies.RealProxy.PropagateOutParameters(IMessage msg, Object[] outArgs, Object returnValue)
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnmessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)

Just have your class implement IRemotingTypeInfo.
pseudo-code looks like:
class InterfaceProxy : RealProxy, IRemotingTypeInfo
{
// snip all the basics
bool IRemotingTypeInfo.CanCastTo(Type fromType, Object o)
{
return interfaces.Contains(fromType);
}
}

Related

Error in binding Given Property of Patient(FHIR .net model as request model) in Core 3.1 App

I have .net core 3.1 web app,
Use HL7.Fhir.R4(1.7.0).
I use Patient model as request model,
[HttpPost]
public Hl7.Fhir.Model.Patient Create([FromBody] Hl7.Fhir.Model.Patient patient)
{
//Use the client to create patient
return patient;
}
Here is a request model,
{
"ResourceType": "Patient",
"Active": true,
"Name": [
{
"Use": 1,
"Family": "Kirk",
"Given": [
"Darshana"
]
},
{
"Use": 0,
"Given": [
"Jim"
]
}
],
"Gender": 1,
"BirthDate": "1994-08-25"
}
Getting below error:
System.InvalidCastException: Unable to cast object of type 'SelectListIterator`2[Hl7.Fhir.Model.FhirString,System.String]' to type 'System.Collections.Generic.IList`1[System.String]'.
at System.Text.Json.JsonSerializer.ApplyValueToEnumerable[TProperty](TProperty& value, ReadStack& state)
at System.Text.Json.JsonPropertyInfoNotNullable`4.OnReadEnumerable(ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.ReadEnumerable(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)
at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
I read code, It is setting value into other object using Linq.Select where it is failing.
How can I bind Given property? Please help.
Maybe this can help someone or person who worked on it can verify or suggest if something they have,
I have created ResourceJsonInputFormatter and ResourceJsonOutputFormatter, Register formatter on startup, ultimately use FhirSerializer to serialize API request and response. Now it works fine.

Trying to use IPipelineBehavior with ASP.NET Core - get System.InvalidCastException

I'm using Mediatr 3's new features for Pipeline Behaviors. Problem is, when I wire them into Mediatr, exceptions (System.InvalidCastException) get thrown for every .Send() call. Handlers get called fine, but when its time for the pipeline behaviors to get called, it fails.
Here's my setup:
services.AddScoped<SingleInstanceFactory>(p => t => p.GetRequiredService(t));
services.AddScoped<MultiInstanceFactory>(p => t => GetRequiredServices(p,t));
services.AddScoped(typeof( IPipelineBehavior<, >), typeof(AddSessionBehavior<, >));
services.AddMediatR();
And my Behavior:
public class AddSessionBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
IHttpContextAccessor Accessor;
public AddSessionBehavior(IHttpContextAccessor anAccessor)
{
this.Accessor = anAccessor;
}
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next)
{
var response = await next();
return response;
}
}
When I send my first message through mediator, I get:
System.InvalidCastException occurred
HResult=0x80004002
Message=Object cannot be stored in an array of this type.
Source=<Cannot evaluate the exception source>
StackTrace:
at System.Array.InternalSetValue(Void* target, Object value)
at System.Array.SetValue(Object value, Int32[] indices)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitClosedIEnumerable(ClosedIEnumerableCallSite closedIEnumerableCallSite, ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitTransient(TransientCallSite transientCallSite, ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass16_0.<RealizeService>b__0(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at MediatR.ServiceCollectionExtensions.GetRequiredServices(IServiceProvider provider, Type serviceType)
at MediatR.Internal.RequestHandlerImpl`2.GetPipeline(TRequest request, RequestHandlerDelegate`1 invokeHandler, MultiInstanceFactory factory)
at MediatR.Internal.RequestHandlerImpl`2.Handle(IRequest`1 request, CancellationToken cancellationToken, SingleInstanceFactory singleFactory, MultiInstanceFactory multiFactory)
at MediatR.Mediator.Send[TResponse](IRequest`1 request, CancellationToken cancellationToken)
at Merlin.Web.Controllers.CourseController.Add(CourseAddVM model)
If I comment out the wiring for my behavior, my handlers get called fine. And the rest of the application seems to work.
What have I done wrong?
I figured it out.
Turns out that somewhere along the way an internal class with the same name as my behavior was created in a different namespace in my application. Probably the result of a "Generate Class definition".
Removing the generated class cleared up the issue.

Issue with Swashbuckle and MediaTypeFormatter

I am trying to apply Swashbuckle on my WebApi. In most cases it works.
For some Api endpoints, for GET, the methods accept JSON from query string as argument. For translating the data from JSON to .NET objects, there are some MediaTypeFormatter at place. The MediaTypeFormatters generally look like below:
public class MyMediaTypeFormatter : JsonMediaTypeFormatter
{
public override bool CanReadType(Type type)
{
return type == typeof (MyType);
}
public override bool CanWriteType(Type type)
{
return false;
}
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger,
CancellationToken cancellationToken)
{
//Do deserialization here
}
}
My WebApi works when invoked from my WebApp as well as from Postman. However, when I invoke the same service from Swagger-UI, it breaks, and complaints about:
{
"Message": "The request contains an entity body but no Content-Type header. The inferred media type 'application/octet-stream' is not supported for this resource.",
"ExceptionMessage": "No MediaTypeFormatter is available to read an object of type 'MyType' from content with media type 'application/octet-stream'.",
"ExceptionType": "System.Net.Http.UnsupportedMediaTypeException",
"StackTrace": " at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)\r\n at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)"
}
Do I need to specify any explicit configuration for this?

ChannelFactory`1[BLLService], cannot be modified while it is in the Opening state

I'm getting an exception in WCF. The problem is that I am randomly getting this exception in Windows service in WCF. Now since I cannot debug production server so I am using log4net for logging.
The exception is random in time and in different functions. It Occurs few in a day with almost 400 to 1000 db entries. Now here is my proxy class code where I am checking the client open state.
public static BLLServiceClient bLLServiceClient
{
get
{
if (_bLLServiceClient == null || _bLLServiceClient.State != CommunicationState.Opened)
{
_bLLServiceClient = new BLLServiceClient(Common.GetBinding(_settings.BLLServiceBinding), new EndpointAddress(_settings.BLLServiceAddress));
_bLLServiceClient.Open();
}
return _bLLServiceClient;
}
set
{
_bLLServiceClient = value;
}
}
Which means if client is not in open state then open it or else return client
The exception is
SetSiteDataStatusInDatabase: ____ The communication object, System.ServiceModel.ChannelFactory`1[BLLService], cannot be modified while it is in the Opening state.
System.ServiceModel
at System.ServiceModel.Channels.CommunicationObject.ThrowIfDisposedOrImmutable()
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.ChannelFactory.EnsureOpened()
at System.ServiceModel.ChannelFactory`1.CreateChannel(EndpointAddress address, Uri via)
at System.ServiceModel.ChannelFactory`1.CreateChannel()
at System.ServiceModel.ClientBase`1.CreateChannel()
at System.ServiceModel.ClientBase`1.CreateChannelInternal()
at System.ServiceModel.ClientBase`1.get_Channel()
at BLLServiceClient.UpdateData(SiteData eSiteData)
at DataHelper.SetSiteDataStatusInDatabase(SiteData oSiteData, CurrentTaskStatus newStatus)
Void ThrowIfDisposedOrImmutable()
System.Collections.ListDictionaryInternal
Full Exception....
System.InvalidOperationException: The communication object, System.ServiceModel.ChannelFactory`1[ BLLService], cannot be modified while it is in the Opening state.
at System.ServiceModel.Channels.CommunicationObject.ThrowIfDisposedOrImmutable()
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.ChannelFactory.EnsureOpened()
at System.ServiceModel.ChannelFactory`1.CreateChannel(EndpointAddress address, Uri via)
at System.ServiceModel.ChannelFactory`1.CreateChannel()
at System.ServiceModel.ClientBase`1.CreateChannel()
at System.ServiceModel.ClientBase`1.CreateChannelInternal()
at System.ServiceModel.ClientBase`1.get_Channel()
at Proxy.BLLService.BLLServiceClient.UpdateData(SiteData eSiteData)
at DataHelper.SetSiteDataStatusInDatabase(SiteData oSiteData, CurrentTaskStatus newStatus)
Tried to search but couldn't find modified type exception
Edit
After using #Agalo answer now the exception has changed to
Exception of type 'System.OutOfMemoryException' was thrown.
System
at System.Uri.CreateHelper(String uriString, Boolean dontEscape, UriKind uriKind, UriFormatException& e)
at System.Uri.TryCreate(String uriString, UriKind uriKind, Uri& result)
at System.ServiceModel.Description.NamingHelper.CheckUriParameter(String ns, String paramName)
at System.ServiceModel.Description.MessagePartDescription..ctor(String name, String ns)
at System.ServiceModel.Description.TypeLoader.CreateParameterPartDescription(XmlName defaultName, String defaultNS, Int32 index, ICustomAttributeProvider attrProvider, Type type)
at System.ServiceModel.Description.TypeLoader.CreateParameterMessageDescription(ParameterInfo[] parameters, Type returnType, ICustomAttributeProvider returnAttrProvider, XmlName returnValueName, String methodName, String defaultNS, String action, XmlName wrapperName, String wrapperNamespace, MessageDirection direction)
at System.ServiceModel.Description.TypeLoader.CreateMessageDescription(MethodInfo methodInfo, Boolean isAsync, Boolean isTask, Type taskTResult, XmlName returnValueName, String defaultNS, String action, XmlName wrapperName, String wrapperNamespace, MessageDirection direction)
at System.ServiceModel.Description.TypeLoader.CreateOperationDescription(ContractDescription contractDescription, MethodInfo methodInfo, MessageDirection direction, ContractReflectionInfo reflectionInfo, ContractDescription declaringContract)
at System.ServiceModel.Description.TypeLoader.CreateOperationDescriptions(ContractDescription contractDescription, ContractReflectionInfo reflectionInfo, Type contractToGetMethodsFrom, ContractDescription declaringContract, MessageDirection direction)
at System.ServiceModel.Description.TypeLoader.CreateContractDescription(ServiceContractAttribute contractAttr, Type contractType, Type serviceType, ContractReflectionInfo& reflectionInfo, Object serviceImplementation)
at System.ServiceModel.Description.TypeLoader.LoadContractDescriptionHelper(Type contractType, Type serviceType, Object serviceImplementation)
at System.ServiceModel.ChannelFactory`1.CreateDescription()
at System.ServiceModel.ChannelFactory.InitializeEndpoint(Binding binding, EndpointAddress address)
at System.ServiceModel.ChannelFactory`1..ctor(Binding binding, EndpointAddress remoteAddress)
at System.ServiceModel.ClientBase`1..ctor(Binding binding, EndpointAddress remoteAddress)
at BLLServiceClient..ctor(Binding binding, EndpointAddress remoteAddress)
at ServiceClients.get_bLLServiceClient()
at SiteDataHelper.get_bLLServiceClient()
at SiteDataHelper.FetchFilesListToDownload(Int32 siteDataId)
System.Uri CreateHelper(System.String, Boolean, System.UriKind, System.UriFormatException ByRef)
System.Collections.ListDictionaryInternal
Full Exception....
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at System.Uri.CreateHelper(String uriString, Boolean dontEscape, UriKind uriKind, UriFormatException& e)
at System.Uri.TryCreate(String uriString, UriKind uriKind, Uri& result)
at System.ServiceModel.Description.NamingHelper.CheckUriParameter(String ns, String paramName)
at System.ServiceModel.Description.MessagePartDescription..ctor(String name, String ns)
at System.ServiceModel.Description.TypeLoader.CreateParameterPartDescription(XmlName defaultName, String defaultNS, Int32 index, ICustomAttributeProvider attrProvider, Type type)
at System.ServiceModel.Description.TypeLoader.CreateParameterMessageDescription(ParameterInfo[] parameters, Type returnType, ICustomAttributeProvider returnAttrProvider, XmlName returnValueName, String methodName, String defaultNS, String action, XmlName wrapperName, String wrapperNamespace, MessageDirection direction)
at System.ServiceModel.Description.TypeLoader.CreateMessageDescription(MethodInfo methodInfo, Boolean isAsync, Boolean isTask, Type taskTResult, XmlName returnValueName, String defaultNS, String action, XmlName wrapperName, String wrapperNamespace, MessageDirection direction)
at System.ServiceModel.Description.TypeLoader.CreateOperationDescription(ContractDescription contractDescription, MethodInfo methodInfo, MessageDirection direction, ContractReflectionInfo reflectionInfo, ContractDescription declaringContract)
at System.ServiceModel.Description.TypeLoader.CreateOperationDescriptions(ContractDescription contractDescription, ContractReflectionInfo reflectionInfo, Type contractToGetMethodsFrom, ContractDescription declaringContract, MessageDirection direction)
at System.ServiceModel.Description.TypeLoader.CreateContractDescription(ServiceContractAttribute contractAttr, Type contractType, Type serviceType, ContractReflectionInfo& reflectionInfo, Object serviceImplementation)
at System.ServiceModel.Description.TypeLoader.LoadContractDescriptionHelper(Type contractType, Type serviceType, Object serviceImplementation)
at System.ServiceModel.ChannelFactory`1.CreateDescription()
at System.ServiceModel.ChannelFactory.InitializeEndpoint(Binding binding, EndpointAddress address)
at System.ServiceModel.ChannelFactory`1..ctor(Binding binding, EndpointAddress remoteAddress)
at System.ServiceModel.ClientBase`1..ctor(Binding binding, EndpointAddress remoteAddress)
at BLLServiceClient..ctor(Binding binding, EndpointAddress remoteAddress)
at ServiceClients.get_bLLServiceClient()
at SiteDataHelper.get_bLLServiceClient()
at SiteDataHelper.FetchFilesListToDownload(Int32 siteDataId)
You can try either of 2 solutions listed below
In your particular case, it might be possible that the inner ChannelFactory is already in Created/Opened state and when you are trying to Open the Proxy, it is calling the Open method of channel Factory which is throwing the invalid operation exception. To Resolve this, you need to check the State of Channel Factory, before opening the Proxy. So you need to validate if the channel factory is already created, then you need not open the proxy again.
_bLLServiceClient.ChannelFactory.State != CommunicationState.Created
Modified function code
public static BLLServiceClient bLLServiceClient
{
get
{
if (_bLLServiceClient == null || _bLLServiceClient.State != CommunicationState.Opened
|| _bLLServiceClient.ChannelFactory.State != CommunicationState.Created)
{
_bLLServiceClient = new BLLServiceClient(Common.GetBinding(_settings.BLLServiceBinding), new EndpointAddress(_settings.BLLServiceAddress));
_bLLServiceClient.Open();
}
return _bLLServiceClient;
}
set
{
_bLLServiceClient = value;
}
}
One of the solution, is to avoid using the Open method. When you call any WCF Service method Open call would be made internally. So It will be invoked automatically.

HTTP Status 415 - Unsupported Media Type when doing POST

So I was trying to do a POST using REST with Postman in Chrome, but after I hit send got error
HTTP Status 415 - Unsupported Media Type
My code and part of the screen shot is included, the pair for the hashmap I tried is duration and 150. I am sure the URL is correct but don't know why the media type is not accepted.
#Path("activities")
public class ActivityResource {
#POST
#Path("activity")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public Activity createActivityParams(MultivaluedHashMap<String,String> formParams){
return null;
}
}
Yeah so as I suspected, the FormMultivaluedMapProvider (which handles MultivaluedMap reading for application/x-www-form-urlencoded Content-Type only allows for MultivaluedMap<String, String> or MultivaluedMap, not MultivaluedHashMap, as you have.
Here is the source for the isReadable (which is called when the runtime looks for a MessageBodyReader to handle the combination of Java/Content-Type types.
#Override
public boolean isReadable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
// Only allow types MultivaluedMap<String, String> and MultivaluedMap.
return type == MultivaluedMap.class
&& (type == genericType || mapType.equals(genericType));
}
As as side note, on the writing side, it's a different story, you can see the isWriteable method, uses isAssignableFrom, which if the isReadable had, you would be able to use the MultivaluedHashMap as your method parameter.
#Override
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return MultivaluedMap.class.isAssignableFrom(type);
}

Resources