WCF Service References and the case of the missing InnerChannel



  • What would cause a WCF Service Reference, created from a WSDL file, not have an InnerChannel member?

    I need to set the OperationTimeout in the standard way:

    serviceClient.InnerChannel.OperationTimeout = new TimeSpan(0, 0, RuntimeConfiguration.TimeoutSeconds);
    

    only to find that it's missing.

    As with everything WCF, I am stumped.



  • Nevermind.

    The ACTUAL ServiceClient contains InnerChannel. It's auto-generated interface, IServiceClient, does not. Since you typically work with interfaces and not types, that's what was fucking me over.

    That's... really annoying.

    So either I need to be NOT working with the interface in this class, or I need to cast it to the concrete class before accessing InnerChannel.

    ((ServiceClient)service).InnerChannel.OperationTimeout = settings.APIOperationTimeout;
    

    Wow that's a shit and a half.



  • If it generates a partial class, (can't remember if it does) you can make an interface inheriting from the interface you're currently using which includes the thing you want. It sounds like the abstraction is leaking somewhat though... is this OperationTimeout different to the timeouts which already exist in the binding?



  • Oh man, I ran into this in the past. I have to run to a series of meetings, but let me dig out my old projects, and I think I can help you with this one.



  • I got it, it's solved. It's just clunky and I don't like it.

    private readonly IService service;
    
    public ServiceWrapper(Settings settings)
    {
        this.settings = settings;
    
        var service = new ServiceClient();
        service.InnerChannel.OperationTimeout = settings.APIOperationTimeout;
        this.service = service;
    }
    

    The real answer is WCF is a shitty API over-complicated to fuck and back, and I hate dealing with it. Those last 3 lines in the constructor should be, at most, 2 lines.

    If it were MY code, I'd just not bother using the interface, but since I know my boss will ask about it, there we go.


  • Discourse touched me in a no-no place

    @blakeyrat said:

    The real answer is WCF is a shitty API over-complicated to fuck and back, and I hate dealing with it.

    I couldn't have said it better myself.



  • Good to hear, because meeting ran loooooooong yesterday. o_O



  • Hey now, I think we can all agree that WCF is a bit more preferable than Web API though, right? Right? 0__0
    Is it just me? =_=


  • Discourse touched me in a no-no place

    @Vaire said:

    Hey now, I think we can all agree that WCF is a bit more preferable than Web API though, right? Right? 0__0Is it just me? =_=

    Surely that's a 🚎


  • FoxDev

    @Vaire said:

    Is it just me?

    Given you don't have to construct a magic incantation from a million confusing XML elements when using Web API (or anything RESTful) just to connect, I'd say it's just you 😛



  • WebAPI sucks too. It's woefully incomplete.

    Did you know you can't make a WebAPI endpoint to allow your user to upload an avatar? Or PDF? Or any type of file? Nope! Doesn't support it. And yet somehow they slapped a version number and shipped it without a gigantic "this product is obviously incomplete!!!" warning on the site. Fucking WebAPI.



  • @blakeyrat said:

    WebAPI sucks too. It's woefully incomplete.

    Did you know you can't make a WebAPI endpoint to allow your user to upload an avatar? Or PDF? Or any type of file? Nope! Doesn't support it. And yet somehow they slapped a version number and shipped it without a gigantic "this product is obviously incomplete!!!" warning on the site. Fucking WebAPI.

    Only @blakeyrat understands me :sadface:
    You tell 'em, Blakey!


  • FoxDev

    Didn't you manage to solve that with some sort of MIME trickery? Or am I thinking of a different issue someone solved that way?



  • I suppose it's good that I know this type of limitation now since it's been strongly suggested I learn WebAPI. Despite being a Java Developer.



  • @RaceProUK said:

    Didn't you manage to solve that with some sort of MIME trickery?

    I solved it by breaking every company rule and every rule of good software development, going outside of the WebAPI framework entirely, and using the old-style .ashx handler classes directly. That solution sucks SO much. But WebAPI forces it.

    Note that I've written by own REST library (for a previous company), as a subclass of the HttpHandler class, which handles pretty much everything WebAPI does in about 300-350 lines of code. So why does WebAPI need megabytes of DLL? Who knows.

    REST APIs aren't hard. They're trivial. Libraries like WebAPI and WCF don't make a difficult thing easy, they make an easy thing difficult.



  • Ehhh, I have working fileuploads with ASP.NET WebAPI? It's not pretty, but it works:

    [Route]
    [HttpPost]
    public async Task<IHttpActionResult> StartRun()
    {
    	if (!Request.Content.IsMimeMultipartContent())
    		throw new NotSupportedException("The request was not a mime/multipart request");
    
    	var provider = new MultipartMemoryStreamProvider();
    	await Request.Content.ReadAsMultipartAsync(provider);
    
    	byte[] fileContents = null;
    
    	foreach (var file in provider.Contents)
    	{
    		switch (file.Headers.ContentDisposition.Name.ToLowerInvariant())
    		{
    			/* Some browsers send the thing with quotes, others send it without... */
    			case "uploadfile":
    			case "\"uploadfile\"":
    				fileContents = await file.ReadAsByteArrayAsync();
    				break;
    		}
    	}
    
    	/* Do something with fileContents */
    	
    	return Ok();
    }
    

    Do note that this solution requires a multipart/form-data form... tossing some bytes against it won't work.



  • Oh to add a little detail, what I was trying to actually do was do file upload and automatic deserialization simultaneously.

    The code I ended up with is vaguely similar to yours, I had to grab the whole multipart and parse out like 30 fields from it and it was a huge mess of shit.

    Anyway, the point is: while it may technically kind of support file uploads, it does so in an entirely half-assed way which doesn't work with its own other features (like automatic deserialization.)



  • They're all better than Remoting. Anything is better than treating something (literally) half-way around the world as if it's right here running in the same process. Fucking Remoting. :angry:


  • Fake News

    @powerlord said:

    I suppose it's good that I know this type of limitation now since it's been strongly suggested I learn WebAPI. Despite being a Java Developer.

    You should, if only to know how limited it's out-of-box setup is. Just don't get confused about its versioning: the API is part of ASP.NET MVC, which is then part of ASP.NET. Now they're completely rebuilding / integrating the MVC and WebAPI frameworks meaning we will get yet another version. In my case I believe I'm using ASP.NET MVC 5.2.3 WebAPI 2.2.

    The framework is extensible where JAX-RS might not always be, though I never would have thought that I had to break out the extensions so quickly if you want to keep things nice and tight:

    • I had to build support for multi-part deserialization (complete with file uploads and nested JSON) using my own MediaTypeFormatter, basically a highly modified version of this "simple" file upload with reflection tacked on - I'll have to dig up the source if someone's interested.
    • In WebAPI you can't simply overload a given URI; I had to build custom attributes to support similar methods with different parameters and different MIME media types. In JAX-RS I would have used the @Consumes annotation and be done with it.

Log in to reply