Search code examples
odataasp.net-web-api2firewallnatportforwarding

OData not working behind router with port address translation (port forwarding)


I have two applications hosted on different computers :

  • An OData web site APP1 on PC1
  • A basic MVC application APP2 on PC2

My router (my.server.com) is configured to forward following request :

  • *:10080 to PC1:80
  • *:20080 to PC2:80

I used Microsoft.OData.Client library to generate OData context and use it from MVC controller. All CRUD operation are working well except when I try to update an entity retrieved from this context.

var entity = await context.Entities.ByKey(id).GetValueAsync();
if (entity != null)
{       
    entity.Property = newValue;

    context.UpdateObject(entity);
    await context.SaveChangesAsync();
}

On SaveChangesAsync method, I get an "unable to connect to the remote server" exception. I first looked into this exception and saw that and it was trying to access my.server.com on port 80 and not 10080. When I look into entity variable context, it says that :

It seems that APP1 is saying "Hello, my entities are accessible from [Entities->Uri]" whereas Microsoft.OData.Client says "Mine are accessible from [BaseUri]" but following code is working :

public async Task<ActionResult> Edit(Entity entity)
{
    context.AttachTo("Entities", entity);
    context.UpdateObject(entity);
    await context.SaveChangesAsync();

    return RedirectToAction("Details", new { id = entity.Id }); 
}

Solution

  • You're sending url requests with a header which includes a port like :10080 to an app hosted on the :80 port. Using NAT, with port modification (PAT), but without correcting the port on the URL can be the source of your problems. To explain it with other words you are asking the router to talk to Mr Smith, and then the router send the request to Mr. Johnson. The problem is that Mr. Johnson sees that the request is for Mr Smith, so that he doesn't like it.

    You should host the services in the same port in yout LAN machines or open the same port in the firewall and do basic NAT (without port mapping) to avoid this conflict between the server port which receives the request and the URL port in your request.