URL Encoding in c# and Asp.net web api

2019-03-30 23:43发布

I have an ASP.NET web api that receives web requests and returns Json data.
browsing to this URL:
http://1.2.3.4/api1/api/values/mypartname will return the following json string:

{
    \"PartName\": \"mypartname\",
    \"PartDes\": \"53.6X53.6APA/ALIM1NOTPAK\",
    \"PartLocation\": \"A36\"
}

but when sending a part name that contains spaces or quotes like this: http://1.2.3.4/api1/api/values/my part na"me i get a 404 - File or directory not found. error.
I'm consuming the json with a .NET 4 Console application like so:

static void Main(string[] args)
    {
        try
        {
            string partName = "TAPE 56 3M 3/4\"";
            WebRequest wr = WebRequest.Create("http://1.2.3.4/api1/api/values/" +
                HttpUtility.UrlEncode(partName));
            wr.Credentials = CredentialCache.DefaultCredentials;
            HttpWebResponse hwr = (HttpWebResponse)wr.GetResponse();
            Stream dataStream = hwr.GetResponseStream();
            StreamReader reader = new StreamReader(dataStream);
            string json = reader.ReadToEnd();
            //some json parsing function
            des(json);
            reader.Close();
            dataStream.Close();
            hwr.Close();

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            Console.ReadKey();
        }
    }

the exception is thrown at this line:HttpWebResponse hwr = (HttpWebResponse)wr.GetResponse(); and the exception message is: The remote server returned an error: (404) Not Found.

Am i doing something wrong with the mypartname? I also tried to manually replace the problematic characters according to this: HTML URL Encoding Reference and using this function:Uri.EscapeDataString(partName) but with no luck.

EDIT
this is the routeConfig definition:

        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );  

and the api GET method:

// GET api/values/5
    public string Get(string id)
    {

        List<dummy> dummies = new List<dummy>();
        string con = "user id=sa;" +
                     "password=1234" +
                     "server=someServer\\someInstance;" +
                     "database=game; " +
                     "connection timeout=30";

        //SqlConnection sqlConn = new SqlConnection(con);
        using (SqlConnection sqlconn = new SqlConnection(con))
        {
            sqlconn.Open();
            StringBuilder sb = new StringBuilder();
            sb.Append("SELECT PART.PARTNAME,PART.PARTDES, PARTPARAMA.LOCATION ");
            sb.Append("FROM PART LEFT JOIN PARTPARAMA ");
            sb.Append("ON PART.PART = PARTPARAMA.PARTPARAM ");
            sb.Append("WHERE PART.PARTNAME = @part");


            using (SqlCommand cmd = new SqlCommand(sb.ToString(), sqlconn))
            {
                cmd.Parameters.AddWithValue("part", id);
                SqlDataReader sdr = cmd.ExecuteReader();
                while (sdr.Read())
                {

                    dummies.Add(new dummy
                    {
                        PartName = sdr.IsDBNull(0) ? "Unknown" : sdr.GetString(0),
                        PartDes = sdr.IsDBNull(1) ? "Unknown" : sdr.GetString(1),
                        PartLocation = sdr.IsDBNull(2) ? "Unknown" : sdr.GetString(2)
                    });
                }
            }
        }

        if (dummies.Count() > 0)
        {
            string json = JsonConvert.SerializeObject(dummies[0]);
            return json;
        }
        else
        {
            string json = JsonConvert.SerializeObject(null);
            return json;
        }

1条回答
别忘想泡老子
2楼-- · 2019-03-31 00:18

EDIT 10 Apr 2015:

I am leaving this answer here for anyone who finds it in a search, however as Kevin states below and Scott Hanselman says here:

[UrlPathEncode] doesn't do what you think it does ... This method was very specific, poorly named, and is now totally obsolete.


I think your problem has more to do with the forward slash in the part name. You can handle the spaces and quotes using

HttpUtility.UrlPathEncode(partName)

instead of HttpUtility.UrlEncode(partName).

Handling the forward slash is more problematic. See this post for more details.

查看更多
登录 后发表回答