Search code examples
c#odataodata-v4

OData v4 calls from browser return URL encoded data


I've created a web API to retrieve data from an SQL Server. I use OData (v4) for the controllers.

This is a striped down version of the main controller.

public class ProtocolsController : ODataController
{
    private readonly MyDbContext _db = new MyDbContext();

    protected override void Dispose(bool disposing)
    {
        _db.Dispose();
        base.Dispose(disposing);
    }

    //Returns all records
    [EnableQuery]
    public IQueryable<Protocol> GetProtocols()
    {
        return _db.Protocols;
    }

    //Returns a single record
    [ODataRoute("Protocols(PYear={year}, PSerialNo={serial}, PType={type})")]
    [EnableQuery]
    public IHttpActionResult GetProtocol([FromODataUri] int year, [FromODataUri] int serial, [FromODataUri] int type)
    {
        return Ok(_db.Protocols.Where(p => p.PYear == year && p.PSerialNo == serial && p.PType == type));
    }
}

This is the GET request I make

http://localhost:49959/Protocols(PYear=2015, PSerialNo=16, PType =1)

And this is the returned JSON from that request

{
  "@odata.context": "http://192.168.2.26:49959/$metadata#Protocols",
  "value": [
    {
      "PYear": 2015,
      "PSerialNo": 16,
      "PType": 1,
      "PProtoTime": null,
      "PNumClass": 0,
      "PIncomingDocSn": "1234",
      "PIncomingYear": 2015,
      "PIncomingDate": "2015-01-02T00:00:00+02:00",
      "PSendMethod": 5,
      "PCreatorDepartment": 3,
      "PCreator": 1,
      "POwnerDepartment": 3,
      "POwner": 1,
      "PDocumentDate": "2015-01-02T00:00:00+02:00",
      "PProtoDate": "2015-01-02T00:00:00+02:00",
      "PDocClass": 3,
      "PPlace": 5,
      "PAuthority": 3,
      "PGrading": 1,
      "PDescription": "ΧΟΡ. ΑΠΟΦΑΣΗΣ ΤΗΣ ΑΡΜΟΔ. ΕΠΙΤΡΟΠΗΣ ΓΙΑ ΤΗΝ ΕΚΔΟΣΗ ΒΙΒΛΙΑΡΙΟΥ ΠΕΡΙΘ. ΑΝΑΣΦ/ΣΤΩΝ ΚΑΙ ΟΙΚΟΝΟΜΙΚΑ ΑΔΥΝΑΤΩΝ",
      "PComments": "",
      "PCancelled": 0,
      "PAddress": "Address",
      "PTown": "Area",
      "PZip": "TK",
      "PEmail": "Email",
      "PFax": "FAX",
      "PTel": "Phone",
      "PCab": "(Φ.Γ) ΓΡΑΦΕΙΟ ΚΟΙΝΩΝΙΚΗΣ ΜΕΡΙΜΝΑΣ",
      "PMoreDestinations": null,
      "PUdfC1": "txt1",
      "PUdfC2": "txt2",
      "PUdfC3": "txt3",
      "PUdfD1": "2015-12-23T00:00:00+02:00",
      "PUdfD2": "2015-12-23T00:00:00+02:00",
      "PUdfD3": "2015-12-23T00:00:00+02:00",
      "PUdfN1": 1,
      "PUdfN2": 2,
      "PUdfN3": 3,
      "PTheme": 1,
      "PSummary": "{\\rtf1\\ansi\\ansicpg1253\\deff0\\deflang1032{\\fonttbl{\\f0\\fswiss\\fcharset0 Tahoma;}{\\f1\\fnil\\fcharset161 MS Sans Serif;}}\r\n\\viewkind4\\uc1\\pard\\lang1033\\f0\\fs16 summary\\lang1032\\f1 \r\n\\par }\r\n",
      "PName": "ΠΑΡΑΣΥΡΗΣ ΓΕΩΡΓΙΟΣ ΤΟΥ ΙΩΑΝΝΗ",
      "PDocState": 2,
      "PCompletionDate": "2015-12-23T13:39:51+02:00",
      "PCompletionNumb": 1
    }
  ]
}

As you can see I have non-latin characters in my data (Greek btw). When I make the request from Postman or Fiddler, I get the above result.

When I try the same request from any browser I get this

{
  "@odata.context":"http://192.168.2.26:49959/$metadata#Protocols","value":[
    {
      "PYear":2015,"PSerialNo":16.0000,"PType":1,"PProtoTime":null,"PNumClass":0,"PIncomingDocSn":"1234","PIncomingYear":2015,"PIncomingDate":"2015-01-02T00:00:00+02:00","PSendMethod":5,"PCreatorDepartment":3,"PCreator":1,"POwnerDepartment":3,"POwner":1,"PDocumentDate":"2015-01-02T00:00:00+02:00","PProtoDate":"2015-01-02T00:00:00+02:00","PDocClass":3,"PPlace":5,"PAuthority":3,"PGrading":1,"PDescription":"\u03a7\u039f\u03a1. \u0391\u03a0\u039f\u03a6\u0391\u03a3\u0397\u03a3 \u03a4\u0397\u03a3 \u0391\u03a1\u039c\u039f\u0394. \u0395\u03a0\u0399\u03a4\u03a1\u039f\u03a0\u0397\u03a3 \u0393\u0399\u0391 \u03a4\u0397\u039d \u0395\u039a\u0394\u039f\u03a3\u0397 \u0392\u0399\u0392\u039b\u0399\u0391\u03a1\u0399\u039f\u03a5 \u03a0\u0395\u03a1\u0399\u0398. \u0391\u039d\u0391\u03a3\u03a6/\u03a3\u03a4\u03a9\u039d \u039a\u0391\u0399 \u039f\u0399\u039a\u039f\u039d\u039f\u039c\u0399\u039a\u0391 \u0391\u0394\u03a5\u039d\u0391\u03a4\u03a9\u039d","PComments":"","PCancelled":0,"PAddress":"Address","PTown":"Area","PZip":"TK","PEmail":"Email","PFax":"FAX","PTel":"Phone","PCab":"(\u03a6.\u0393) \u0393\u03a1\u0391\u03a6\u0395\u0399\u039f \u039a\u039f\u0399\u039d\u03a9\u039d\u0399\u039a\u0397\u03a3 \u039c\u0395\u03a1\u0399\u039c\u039d\u0391\u03a3","PMoreDestinations":null,"PUdfC1":"txt1","PUdfC2":"txt2","PUdfC3":"txt3","PUdfD1":"2015-12-23T00:00:00+02:00","PUdfD2":"2015-12-23T00:00:00+02:00","PUdfD3":"2015-12-23T00:00:00+02:00","PUdfN1":1.0000,"PUdfN2":2.0000,"PUdfN3":3.0000,"PTheme":1,"PSummary":"{\\rtf1\\ansi\\ansicpg1253\\deff0\\deflang1032{\\fonttbl{\\f0\\fswiss\\fcharset0 Tahoma;}{\\f1\\fnil\\fcharset161 MS Sans Serif;}}\r\n\\viewkind4\\uc1\\pard\\lang1033\\f0\\fs16 summary\\lang1032\\f1 \r\n\\par }\r\n","PName":"\u03a0\u0391\u03a1\u0391\u03a3\u03a5\u03a1\u0397\u03a3 \u0393\u0395\u03a9\u03a1\u0393\u0399\u039f\u03a3 \u03a4\u039f\u03a5 \u0399\u03a9\u0391\u039d\u039d\u0397","PDocState":2,"PCompletionDate":"2015-12-23T13:39:51+02:00","PCompletionNumb":1
    }
  ]
}

For some reason the non-latin characters are returned URL encoded. Is there something I need to setup on my API side or something I had to do with my browser?

P.S. I don't know if it will be of any importance, but I use Owin as well.


Solution

  • The response with string data of the form \uXXXX is simply using a different character encoding (not URL encoding) than the response containing Greek characters. The strings are functionally equivalent.

    Your browser is probably sending an Accept-Charset header with a value of us-ascii; or it may be sending a charset parameter in the Accept header (less likely). On the other hand, Postman and Fiddler are probably not sending Accept-Charset at all (because they only send what you explicitly tell them to), and so the character encoding on the server is defaulting to utf-8 (which can represent Greek directly). Use the developer tools in your browser to inspect the headers being sent with your request.