I created a .Net web service:
public class UsersController : ApiController
{
[System.Web.Http.HttpPost]
public void Post(string value)
{
SqlConnection connection = new SqlConnection("Data Source=198.71.226.6;Integrated Security=False;User ID=AtallahMaroniteDB;Password=a!m?P#$$123;Database=AtallahPlesk_;Connect Timeout=15;Encrypt=False;Packet Size=4096");
String query = "INSERT INTO Members(LastName, FirstName, Gender, MobileNumber, EmailAddress, Job, Address) VALUES " +
"(#LastName, #FirstName, #Gender, #MobileNumber, #EmailAddress, #Job, #Address)";
SqlCommand command = new SqlCommand(query, connection);
try
{
JavaScriptSerializer json_serializer = new JavaScriptSerializer();
PersonModel person = json_serializer.Deserialize<PersonModel>(value);
command.Parameters.Add("#LastName", person.LastName);
command.Parameters.Add("#FirstName", person.FirstName);
command.Parameters.Add("#Gender", person.Gender);
command.Parameters.Add("#MobileNumber", person.MobileNumber);
command.Parameters.Add("#EmailAddress", person.EmailAddress);
command.Parameters.Add("#Job", person.Job);
command.Parameters.Add("#Address", person.Address);
connection.Open();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException.ToString());
}
}
}
And the following is my routing config:
RouteTable.Routes.MapHttpRoute(
name: "MyApi",
routeTemplate: "api/{controller}/{action}/{value}"
);
When I am calling this web service from an Android or iOS application, I am getting the following error:
No HTTP resource was found that matches the request URI
'http://www.mytestdomain.com/api/users/post'
Below is the android code:
JSONObject dato = POST(person); // This method converts the Person object to JSONObject
String text = null;
try {
HttpPost post = new HttpPost("http://www.mytestdomain.com/api/users/post");
StringEntity entity = new StringEntity(dato.toString());
entity.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(entity);
HttpResponse response = httpClient.execute(post);
HttpEntity entityResponse = response.getEntity();
text = getASCIIContentFromEntity(entityResponse);
} catch ( IOException ioe ) {
ioe.printStackTrace();
}
Please note that when I call this web service from postman, it's posting the data successfully.
Please let me know if you need any further details.
You need to update your route template to make sure that you get a valid match for your request.
Here is what a valid template would look like for your API. Note this is specific to the UsersController as the defaults: has been set to controller = "Users" which will map to the UsersController
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Attribute routing.
config.MapHttpAttributeRoutes();
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "MyApi",
routeTemplate: "api/users/{action}",
defaults: new { controller = "Users" }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
From your code example you are sending the model as json and then trying to manually parse it on the server. You can let the framework parse the model with its model binders based on the Content-Type of the request. This will allow you to update your action to accept the actual object model instead of a string.
public class UsersController : ApiController {
//eg: POST api/users/post
[HttpPost]
public IHttpActionResult Post(PersonModel person) {
if (person == null) return BadRequest();
try
{
SqlConnection connection = new SqlConnection("Data Source=198.71.226.6;Integrated Security=False;User ID=AtallahMaroniteDB;Password=a!m?P#$$123;Database=AtallahPlesk_;Connect Timeout=15;Encrypt=False;Packet Size=4096");
String query = "INSERT INTO Members(LastName, FirstName, Gender, MobileNumber, EmailAddress, Job, Address) VALUES " +
"(#LastName, #FirstName, #Gender, #MobileNumber, #EmailAddress, #Job, #Address)";
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.Add("#LastName", person.LastName);
command.Parameters.Add("#FirstName", person.FirstName);
command.Parameters.Add("#Gender", person.Gender);
command.Parameters.Add("#MobileNumber", person.MobileNumber);
command.Parameters.Add("#EmailAddress", person.EmailAddress);
command.Parameters.Add("#Job", person.Job);
command.Parameters.Add("#Address", person.Address);
connection.Open();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException.ToString());
return InternalServerError();
}
return Ok();
}
}
You also need to make sure the request sent is correct so you can get a match
Here is a raw example request snippet
POST /api/users/post HTTP/1.1
Host: http://www.mytestdomain.com
Content-Type: application/json
...
Content-Length: 163
{"LastName":"Doe","FirstName":"Jane","Gender":"Female","MobileNumber":"+1234567890","EmailAddress":"jane.doe#example.com","Job":"Developer","Address":"My address"}
Try inspecting the requests sent from the mobile to make sure its being sent correctly. Something like Fiddler.
Related
I am having problems invoking the PayPal IPN. I dont know which URL to give or which URL i am meant to give. I have looked all over the internet for help but there does not seem to be anything available hence why i have come here.
So firstly, i have the PaymentWithPaypal Action
public ActionResult PaymentWithPaypal(int? id, Page page)
{
//getting the apiContext as earlier
APIContext apiContext = Models.Configuration.GetAPIContext();
try
{
string payerId = Request.Params["PayerID"];
if (string.IsNullOrEmpty(payerId))
{
string baseURI = Request.Url.Scheme + "://" + Request.Url.Authority + "/ControllerName/PaymentWithPayPal?";
var guid = Guid.NewGuid().ToString();
//CreatePayment function gives us the payment approval url
//on which payer is redirected for paypal acccount payment
var createdPayment = this.CreatePayment(apiContext, baseURI + "guid=" + guid);
//get links returned from paypal in response to Create function call
var links = createdPayment.links.GetEnumerator();
string paypalRedirectUrl = null;
while (links.MoveNext())
{
Links lnk = links.Current;
if (lnk.rel.ToLower().Trim().Equals("approval_url"))
{
//saving the payapalredirect URL to which user will be redirected for payment
paypalRedirectUrl = lnk.href;
}
}
// saving the paymentID in the key guid
Session.Add(guid, createdPayment.id);
return Redirect(paypalRedirectUrl);
}
else
{
// This section is executed when we have received all the payments parameters
// from the previous call to the function Create
// Executing a payment
var guid = Request.Params["guid"];
var executedPayment = ExecutePayment(apiContext, payerId, Session[guid] as string);
if (executedPayment.state.ToLower() != "approved")
{
return View("FailureView");
}
}
}
catch (Exception ex)
{
Logger.Log("Error" + ex.Message);
return View("FailureView");
}
return View("SuccessView");
}
This is the code for the IPN.
[HttpPost]
public HttpStatusCodeResult Receive()
{
//Store the IPN received from PayPal
LogRequest(Request);
//Fire and forget verification task
Task.Run(() => VerifyTask(Request));
//Reply back a 200 code
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
private void VerifyTask(HttpRequestBase ipnRequest)
{
var verificationResponse = string.Empty;
try
{
var verificationRequest = (HttpWebRequest)WebRequest.Create("https://www.sandbox.paypal.com/cgi-bin/webscr");
//Set values for the verification request
verificationRequest.Method = "POST";
verificationRequest.ContentType = "application/x-www-form-urlencoded";
var param = Request.BinaryRead(ipnRequest.ContentLength);
var strRequest = Encoding.ASCII.GetString(param);
//Add cmd=_notify-validate to the payload
strRequest = "cmd=_notify-validate&" + strRequest;
verificationRequest.ContentLength = strRequest.Length;
//Attach payload to the verification request
var streamOut = new StreamWriter(verificationRequest.GetRequestStream(), Encoding.ASCII);
streamOut.Write(strRequest);
streamOut.Close();
//Send the request to PayPal and get the response
var streamIn = new StreamReader(verificationRequest.GetResponse().GetResponseStream());
verificationResponse = streamIn.ReadToEnd();
streamIn.Close();
}
catch (Exception exception)
{
Logger.Log("Error" + exception.Message);
//Capture exception for manual investigation
}
ProcessVerificationResponse(verificationResponse);
}
private void LogRequest(HttpRequestBase request)
{
// Persist the request values into a database or temporary data store
}
private void ProcessVerificationResponse(string verificationResponse)
{
if (verificationResponse.Equals("VERIFIED"))
{
Logger.Log("Verified");
// check that Payment_status=Completed
// check that Txn_id has not been previously processed
// check that Receiver_email is your Primary PayPal email
// check that Payment_amount/Payment_currency are correct
// process payment
}
else if (verificationResponse.Equals("INVALID"))
{
Logger.Log(verificationResponse);
}
else
{
//Log error
}
}
Now to clear things up. My understanding of the IPN is that when a customer purchases an item, the SELLER will get an email telling them that they have sold a product and then from this you can access transactionId etc.
So in my view i have a form with a button that looks like this.
#Html.ActionLink("Buy Now", "PaymentWithPaypal", new { Id = Model.Id, #class = "" })
This is what takes the customer to paypal where they can then purchase but this is where i am stuck because im not sure how to call the IPN or if it needs its own view.
ANY CLARITY WOULD BE OF MUCH HELP AT THIS MOMENT IN TIME.
One way is to put this under PayPal account settings. Once you click on your "App", below it you see the redirect url option. Just add it there. Paypal .net sdk doesn't have the option to pass notify_url. All other modes have. Because, paypal.net sdk accepts return_url which is usually the same action method as also mentioned in your code.
Check this:
https://developer.paypal.com/docs/classic/ipn/integration-guide/IPNSetup/#
In case you want to achieve real time events, you need to use webhooks now. Documentation below:
https://github.com/paypal/PayPal-NET-SDK/wiki/Webhook-Event-Validation
I have the following to post JSON to a C# Web API:
submitForm(data: any): Observable<Response> {
return this.http.post(
'https://localhost:44396/api/PostNewComputer/AddItem/?=', data,
{ headers: new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' }) }).subscribe(data => { return "test"; });
}
And the API controller:
public class PostNewComputerController : ApiController
{
[HttpPost]
public IHttpActionResult AddItem(HttpRequestMessage request)
{
//var dynamicObject = Json.Decode(jsonString);
var jsonString = request.GetQueryNameValuePairs();
string message;
using (SqlConnection con = new SqlConnection("data source = MYSERVER; initial catalog = AssetDB; integrated security = SSPI; persist security info = True; Trusted_Connection = Yes"))
{
using (SqlCommand cmd = new SqlCommand("POST_NEW_COMPUTER", con) { CommandType = CommandType.StoredProcedure })
{
try
{
cmd.Parameters.Add(new SqlParameter("#JSON_TEXT", SqlDbType.NVarChar)).Value = jsonString;
con.Open();
cmd.ExecuteNonQuery();
con.Close();
message = "Item Successfully Added";
}
catch (Exception e)
{
//throw e;
message = e.Message;
}
}
return Ok(message);
}
}
}
I am trying to create a response message from the POST call that is then fed back to the webpage when the user submits the form to show that the post has worked.
However, this current setup doesn't work and I am struggling to solves this.
Is there a correct way to do this properly?
Use HttpResponseMessage to post back message as:
[HttpPost]
[ResponseType(typeof(string))]
public HttpResponseMessage AddItem(HttpRequestMessage request)
{
HttpResponseMessage response = null;
string message = string.Empty;
try
{
.....
message = "Item Successfully Added";
}
catch (Exception e)
{
.....
message = e.Message;
}
response = Request.CreateResponse<string>(HttpStatusCode.OK, message);
return response;
}
The problem is in your Angular service. Your API is correct
You're trying to subscribe to the response from your API before mapping it back to json(), you need to do the following, see below:
Firstly this is what should be in your component:
submitForm(data: any): Observable<Response> {
//this url can't be correct?
let url:string = 'https://localhost:44396/api/PostNewComputer/AddItem/?=';
return this.http.post(url, data, this._headers())
.map((res:Response) => res.json());
}
//Created a method to do the headers for you
private _headers():RequestOptionsArgs {
let headers:Headers = new headers();
headers.append('Content-Type', 'application/json');
let options:RequestOptionsArgs = new RequestOptions();
options.headers = headers;
return options;
}
You would then call your service from your component as follows:
public functionName():void {
this.service.submitForm(data)
.subscribe((res:any) => {
//this will contain your response
},
(error:any) => {
//this will contain your error
});
}
You need to ensure the model you're posting matches the model expected. With regards to the URL you are posting to, that seems incorrect, is it not https://localhost:44396/api/PostNewComputer/AddItem/?
I am trying to upload .csv file into my application. the code is woking properly at my local pc. but it gives me an error related to jquery when i deployed the same code on my UAT server.
The error details are as follow,
POST https://www.dummy.com/Customers/UploadCustomersLead 404 (Not
Found)
send # jquery-1.11.1.min.js:4
ajax # jquery-1.11.1.min.js:4
(anonymous) # Customers:592
dispatch # jquery-1.11.1.min.js:3
r.handle # jquery-1.11.1.min.js:3
my controller code is as follow,
[HttpPost]
public JsonResult UploadCustomersLead()
{
string sMessage = "";
bool bStatus = true;
bool bError = false;
System.IO.StreamWriter file = new System.IO.StreamWriter(System.Configuration.ConfigurationManager.AppSettings["LogFile"].ToString());
file.WriteLine("inside upload cust");
var attachedFile = System.Web.HttpContext.Current.Request.Files["CsvDoc"];
if (attachedFile != null && attachedFile.ContentLength > 0)
{
string fileName = Path.GetFileName(attachedFile.FileName);
string path = Path.Combine(Server.MapPath(ConfigManager.GetUploadCSVFilePathForUpload), fileName);
file.WriteLine("inside upload cust path:" + path);
try
{
attachedFile.SaveAs(path);
DataTable dt = ConvertCSVToDataTable(path); //DataTable dt = CommonFunction.ConvertCSVToDataTable(path); //Are not working because this method is in PNRMSystem.BLL/CommonBusinessLogic.cs file.
List<string> l = new List<string>();
if (dt.Rows.Count > 0)
{
MerchantMasterService.MerchantMasterClient merchantMasterClient = new MerchantMasterService.MerchantMasterClient();
foreach (DataRow row in dt.Rows)
{
MerchantMasterService.AddCustomerLeadsFromAdminRequest addCustomerLeadsFromMerchantDashboardRequest = new MerchantMasterService.AddCustomerLeadsFromAdminRequest
{
RegisteredMobileNumber = row["SellerNumber"].ToString(), //MerchantMobileNumber;
CustomerMobileNumber = row["CustomerNumber"].ToString(), //CustomerMobileNumber,
CustomerName = row["CustomerName"].ToString(), //CustomerName,
Address = row["Address"].ToString(), //Address,
BillAmount = Convert.ToDecimal(row["BillAmount"].ToString()) //BillAmount
};
MerchantMasterService.AddCustomerLeadsFromAdminResponse addCustomerLeadsFromMerchantDashboardResponse = merchantMasterClient.AddCustomerLeadsFromAdmin(addCustomerLeadsFromMerchantDashboardRequest);
if (addCustomerLeadsFromMerchantDashboardResponse.StatusCode.ToString().ToLower().Equals("failure"))
{
l.Add(row["CustomerNumber"].ToString());
}
}
}
dt.Dispose();
ModelState.Clear();
var Number = l.Count > 0 ? string.Join(",", l) : "None";
sMessage = "Total Records : " + dt.Rows.Count + "</br>" + "Total Success : " + (dt.Rows.Count - l.Count) + "<br/>" + "Total failure : " + l.Count + "<br/>" + "Total failure Number : " + Number;
}
catch (Exception ex)
{
ModelState.AddModelError("File", ex.Message.ToString());
CreateLog.Error(this.GetType(), "Error occured on UploadCustomersLead action in Customers controller in merchant dashboard.", ex);
bError = true;
sMessage = "An error occured. Please try again.";
throw;
}
finally
{
if (System.IO.File.Exists(path))
{
System.IO.File.Delete(path);
}
file.Close();
}
}
else
{
ModelState.AddModelError("File", "Please Select Your file");
}
return Json(new { Message = sMessage, Status = bStatus, Error = bError }, JsonRequestBehavior.AllowGet);
}
and .cshtml file jquery code is as follow,
$("#btnUploadCustLeads").click(function () {
var fileExtension = ['csv'];
if ($("#IDofTheUploader").val() == "" || $("#IDofTheUploader").val() == null || $.inArray($("#IDofTheUploader").val().split('.').pop().toLowerCase(), fileExtension) == -1) {
$('#statusBoxUploadCustLeads').removeClass('alert-danger').addClass('alert-success').show(500, function () {
$('#statusMessageUploadCustLeads').html("Kindly select the .csv file to be uploaded.");
});
}
else {
$('#imgLoadingAddCustomer').removeAttr("style");
var fileUpload = document.getElementById("IDofTheUploader");
if (fileUpload.value != null) {
var uploadFile = new FormData();
var files = $("#IDofTheUploader").get(0).files;
// Add the uploaded file content to the form data collection
if (files.length > 0) {
uploadFile.append("CsvDoc", files[0]);
$.ajax({
url: "/Customers/UploadCustomersLead",
contentType: false,
processData: false,
data: uploadFile,
type: 'POST',
success: function (data) {
$('#statusBoxUploadCustLeads').removeClass('alert-danger').addClass('alert-success').show(500, function () {
$('#statusMessageUploadCustLeads').html(data.Message);
ClearUploadCustLeadsControls();
});
},
complete: function () {
$('#imgLoadingAddCustomer').css("display", "none");
}
});
}
}
else {
$('#statusBoxUploadCustLeads').removeClass('alert-danger').addClass('alert-success').show(500, function () {
$('#statusMessageUploadCustLeads').html("File to be uploaded can not be bank.");
});
}
}
});
#princeofmince , I have tried route configuration with
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapHttpRoute(
name: "CallMethodByName",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Account", action = "Index", id = UrlParameter.Optional }
);
in routeconfig.cs file on server but didn't work and my action method is of [httppost] method not [httpget]
I would comment but I have insufficient rep.
Try checking the route configuration of the UAT server. I had similar errors when I had multiple GET methods on a controller - I needed to specify a route which took the method name as an argument using something like this:
routes.MapHttpRoute(
name: "CallMethodByName",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
If this piece of configuration is not in the UAT server it won't handle the request properly and return a 404 error.
EDIT: The new config should go below the older one (more specific instructions should go later). This should work with post as well as get methods. How does your test config compare to the UAT config?
I've worked out all the problems with the WEB API implementation in Umbraco (Token & Member creation in an http post), the problem I'm having here is this final macro, I've created to drop in an Umbraco page, it will not collect the token and email from the querystring. I keep getting a System.Data.SqlClient.SqlException (expects the parameter '#token', which was not supplied) Am I not able to grab a querystring in Umbraco, or more specifically an Umbraco macro?
namespace ****.SSO
{
public partial class ****SSOMacro : System.Web.UI.UserControl,
umbraco.editorControls.userControlGrapper.IUsercontrolDataEditor
{
static Token token = new Token();
static string connStr = ConfigurationManager.ConnectionStrings["umbracoDbDSN"].ConnectionString;
protected void Page_Load(object sender, EventArgs e)
{
try{
**string tmpToken = Request.QueryString["token"];
string tmpEmail = Request.QueryString["email"];
//Check If Token Still Exists
using (SqlConnection myConnection = new SqlConnection(connStr))
{
myConnection.Open();
SqlCommand command = new SqlCommand("SELECT * FROM [DBTokenTable] WHERE tokens = #token and email = #email and valid = 'true'", myConnection);
command.Parameters.AddWithValue("#token", tmpToken);
command.Parameters.AddWithValue("#email", tmpEmail);
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
token = new Token { token = reader["Tokens"].ToString(), email = reader["Email"].ToString(), valid = reader["Valid"].ToString() };
}
}
myConnection.Close();
}**
}
catch (Exception ex)
{
string error = ex.ToString();
//Log Any Form Cookies Out
FormsAuthentication.SignOut();
RawrLabel.Text = error;
//Response.Redirect(HttpUtility.UrlEncode("https://google.com/#q=" + error));
}
}
private string _umbval;
public object value
{
get { return _umbval; }
set { _umbval = value.ToString(); }
}
I was adding my macro onto a template page with Razor, so MVC didn't recognize the web forms Request.Querystring["value"] method. Instead just add the macro directly onto a content page with a Richtext editor.
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;
}
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.