Here is my code for a mass unsubscriber i am making, currently everything works - other than the unsubscribe feature.. (Typical huh)
public void UnSubUsers()
{
string feedUrl = "http://gdata.youtube.com/feeds/api/users/" + username.Text + "/subscriptions";
YouTubeQuery query = new YouTubeQuery(feedUrl);
subFeed = service.GetSubscriptions(query);
YouTubeRequestSettings yts = new YouTubeRequestSettings("Unsubscriber", DEVKEY, username.Text, password.Text);
YouTubeRequest request = new YouTubeRequest(yts);
int i = 0;
int x = 0;
x = (listBox1.Items.Count);
for (i=0;i<x ;i++ )
{
string uname = listBox1.Items[i].ToString();
uname=uname.Substring(42);
uname = uname.Remove(uname.LastIndexOf("/"));
Subscription s = new Subscription();
s.Type = SubscriptionEntry.SubscriptionType.channel;
s.UserName = uname;
//MessageBox.Show(uname); //Displays the username so that we know if it is correct
try
{
s.AtomEntry.EditUri = "http://gdata.youtube.com/feeds/api/users/" + username.Text + "/subscriptions";
s.SubscriptionEntry.EditUri = "http://gdata.youtube.com/feeds/api/users/" + username.Text + "/subscriptions";
request.Delete(s);
}
catch (ArgumentNullException e)
{
MessageBox.Show(e.ToString(), "Error");
}
catch (GDataRequestException e)
{
MessageBox.Show(e.ToString(), "Error");
}
}
}
(Also available at http://pastebin.com/LnKMYCJp)
When the code "reaches" request.Delete(s) it gives me this error:
Google.GData.Client.GDataRequestException: Execution of request failed: http://gdata.youtube.com/feeds/api/users/iWinterHD/subscriptions --->System.Net.WebException: The remote server returned an error: (400) Bad Request.
at System.Net.HttpWebRequest.GetResponse()
at Google.GData.Client.GDataRequest.Execute()
--- End of inner exception stack trace ---
at Google.GData.Client.GDataRequest.Execute()
at Google.GData.Client.GDataGAuthRequest.Execute(Int32 retryCounter)
at Google.GData.Client.GDataGAuthRequest.Execute()
at Google.GData.Client.Service.Delete(Uri uriTarget, String eTag)
at Google.GData.Client.FeedRequest1.Delete[Y](Y entry)
at Unsubscriber.SubForm.UnSubUsers() in C:\Users\iWinterHD\documents\visual studio 2010\Projects\Unsubscriber\Unsubscriber\SubForm.cs:line 112
Does anybody know how to fix this, I have been trying to get this working for around 2 hours and I am still getting this error, no matter what I try
When i used fiddler to find out info about the connection this was the header:
DELETE /feeds/api/users/iWinterHD/subscriptions HTTP/1.1
Content-Type: application/atom+xml; charset=UTF-8
User-Agent: G-Unsubscriber/GDataGAuthRequestFactory-CS-Version=2.1.0.0--IEnumerable
X-GData-Key: key=DEVELOPER_KEY
Authorization: GoogleLogin auth=DQAAAMgAAAAfAWmos6z7rpaY8JrK2RNK4Urf7Riu_putKeGgV1KFH5OEmAYA2t5w0DWXbVQJnizQiPmLSl-4D0eCozYn5jVp4DWs4Rpao3udc3eTIC9wibBGRe640m7zZjl96UnFMyf-fJDk0VrTIcAw74S7_WhwBaRDjLS77EOWfERw066NmcYO-2QB_6WZ4Y0o3Y4haVn_pRokm8ckyuTRWJf6cES1yVlZ4fP5diUySVsH7EaHLiUcAquUl7GWCMdF_JbjRVVxvgeMW1zV757JW8l841uk
GData-Version: 2.0
Host: gdata.youtube.com
Connection: Keep-Alive
However the Google Developers example is this:
DELETE /feeds/api/users/default/subscriptions/SUBSCRIPTION_ID HTTP/1.1
Host: gdata.youtube.com
Content-Type: application/atom+xml
Authorization: Bearer ACCESS_TOKEN
GData-Version: 2
X-GData-Key: key=DEVELOPER_KEY
Hopefully that gives a little heads up :)
After a bit of playing around with the API I think I've found the solution.
The AtomEntry.EditUri needs to be the same as the URI to the individual subscription. As it happens this is already stored in the SubscriptionEntry object (which you're overwriting).
Your code should look something like:
itemToRemove.AtomEntry.EditUri = itemToRemove.SubscriptionEntry.EditUri;
Here's the code I used to test this:
var subscriptionsUrl =
"http://gdata.youtube.com/feeds/api/users/warmthonthesoul/subscriptions";
var settings = new YouTubeRequestSettings([...]);
var request = new YouTubeRequest(settings);
var query = new YouTubeQuery(subscriptionsUrl);
var feed = request.GetSubscriptionsFeed("warmthonthesoul").Entries;
var itemToRemove = feed.SingleOrDefault(x =>
x
.SubscriptionEntry
.Title.Text.Contains("Triforcefilms"));
if(itemToRemove != null)
{
itemToRemove.AtomEntry.EditUri = itemToRemove
.SubscriptionEntry
.EditUri;
request.Delete(itemToRemove);
Console.WriteLine("Item removed");
}
Console.ReadLine();
}
After searching through all the variables for around 4 hours i ended up stumbling upon the ID variable, which i later discovered needed to be passed to the final URL in order to remove the subscription WITH that ID, I tested it and it worked perfectly!
public void ListSubs()
{
string feedUrl = "http://gdata.youtube.com/feeds/api/users/" + username.Text + "/subscriptions";
YouTubeQuery query = new YouTubeQuery(feedUrl);
try
{
subFeed = service.GetSubscriptions(query);
foreach (SubscriptionEntry entry in subFeed.Entries)
{
string id = entry.Id.AbsoluteUri;
id = id.Substring(id.LastIndexOf(":")+1);
listBox1.Items.Add(id);
string usrname = entry.Content.Src.Content;
usrname = usrname.Substring(42);
usrname = usrname.Remove(usrname.LastIndexOf("/"));
listBox2.Items.Add(usrname);
}
}
catch(GDataRequestException e)
{
MessageBox.Show(e.ToString(), "Error:");
}
}
public void UnSubUsers()
{
YouTubeRequestSettings yts = new YouTubeRequestSettings("Unsubscriber", DEVELOPER_KEY, username.Text, password.Text);
YouTubeRequest request = new YouTubeRequest(yts);
int i = 0;
int x = 0;
x = (listBox1.Items.Count);
for (i=0;i<x ;i++ )
{
string uname = listBox1.Items[i].ToString();
yts = new YouTubeRequestSettings("Unsubscriber", DEVELOPER_KEY, username.Text, password.Text);
request = new YouTubeRequest(yts);
Subscription s = new Subscription();
s.Type = SubscriptionEntry.SubscriptionType.channel;
s.UserName = uname;
s.Id = listBox1.Items[i].ToString()
try
{
s.AtomEntry.EditUri = "http://gdata.youtube.com/feeds/api/users/" + username.Text + "/subscriptions" + "/" + listBox1.Items[i].ToString();
request.Delete(s);
}
catch (ArgumentNullException e)
{
}
catch (GDataRequestException e)
{
}
}
}
I had to add the subscription ID to the URL i was using to delete the subscription, here is my code to add the subscription ID to the listbox i originally used to store usernames, it turns out you can't pass usernames to the Delete method, but this works just as well because i added a second listbox to find the usernames of the subscription IDs
string id = entry.Id.AbsoluteUri;
id = id.Substring(id.LastIndexOf(":")+1);
listBox1.Items.Add(id);
This code gets the subscription ID from the entry variable, you then add the subscription ID to the EditUri variable:
s.AtomEntry.EditUri = "http://gdata.youtube.com/feeds/api/users/" + username.Text + "/subscriptions" + "/" + listBox1.Items[i].ToString();
request.Delete(s);
My mass unsubscriber is now complete!
Many thanks to #JamieDixon for all his wonderful help!
Related
I am a begginer and i work in a MVC project which I cant understand it well yet.
I can't understand where does the API takes data from when I try to connect in Login Screen.
It doesn't use Entity Framework and there isn't a json with the data.
When I enter Id and Pass it calls an API (GetAPIResponse) which somehow finds that is correct.
Need help to understand the code and the logic behind it.
LoginBL class contains:
public bool IsAuthenticated(LoginEntity user)
{
string url = string.Empty;
string callType = string.Empty;
string server = string.Empty;
try
{
// get URL, Call type, Server from config file
url = ConfigurationManager.AppSettings["login_url"].ToString();
callType = ConfigurationManager.AppSettings["calltype"].ToString();
server = ConfigurationManager.AppSettings["server"].ToString();
// Encrypt password
string password = Scrambler.GenerateMD5Hash(user.Password);
// Prepare content for the POST request
string content = #"calltype=" + callType + "&server=" + server + "&user=" + user.UserName + "&pass=" + password + "";
Debug.WriteLine("Callcenter login url: " + content);
HttpResponseMessage json_list = ApiCallBL.GetAPIResponse(url, content);
LoginResponseEntity obj = new LoginResponseEntity();
obj = JsonConvert.DeserializeObject<LoginResponseEntity>(json_list.Content.ReadAsStringAsync().Result);
Debug.WriteLine(callType + " Response: " + json_list.Content.ReadAsStringAsync().Result);
//if API resultCode return 0 then user details and token save in session for further use
if (obj.ResultCode == 0)
{
int restrict = obj.UserInfo.RestrictCallType.HasValue ?
obj.UserInfo.RestrictCallType.Value : 0;
HttpContext.Current.Session["user_id"] = obj.UserInfo.usr_id;
HttpContext.Current.Session["user_name"] = obj.UserInfo.usr_username;
HttpContext.Current.Session["user_group_id"] = obj.UserInfo.UserGroupID;
HttpContext.Current.Session["groupid"] = obj.UserInfo.groupid;
HttpContext.Current.Session["token"] = obj.Token;
HttpContext.Current.Session["web_server_url"] = obj.ServerInfo.web_server_url;
HttpContext.Current.Session["centerX"] = obj.ServerInfo.DefaultGeoX;
HttpContext.Current.Session["centerY"] = obj.ServerInfo.DefaultGeoY;
HttpContext.Current.Session["dateFormat"] = obj.ServerInfo.dateFormat;
HttpContext.Current.Session["currency"] = obj.ServerInfo.currency;
HttpContext.Current.Session["customer_img"] = obj.ServerInfo.customer_img;
HttpContext.Current.Session["groups"] = obj.groups;
HttpContext.Current.Session["restrict_call_type"] = restrict ;
Debug.WriteLine("obj.UserInfo.UserGroupID " + obj.UserInfo.UserGroupID);
Debug.WriteLine("obj.UserInfo.groups " + obj.groups);
//HttpContext.Current.Session["defaultLanguage"] = obj.ServerInfo.defaultLanguage;
HttpCookie cookie = new HttpCookie("Login");
// if remember me checked then user name and password stored in cookie else cookes is expired
if (user.RememberMe)
{
cookie.Values.Add("user_name", obj.UserInfo.usr_username);
cookie.Values.Add("pwd", user.Password);
cookie.Expires = DateTime.Now.AddDays(15);
HttpContext.Current.Response.Cookies.Add(cookie);
}
else
{
cookie.Expires = DateTime.Now.AddDays(-1);
HttpContext.Current.Response.Cookies.Add(cookie);
}
return true;
}
else
{
//ResultCode -5 :Invalid Login ,-1:Database Error ,-2:Server Error ,-3:Invalid Parameter specified ,-4:Invalid Token
return false;
}
}
catch
{
throw;
}
finally
{
url = string.Empty;
callType = string.Empty;
server = string.Empty;
}
}
Okay here after converts pass to MD5 creates a "string content" with the information given.
Then in next line (HttpResponseMessage json_list = ApiCallBL.GetAPIResponse(url, content);) calls the API with the url and content as parameters where it finds if the data exists.
API code:
public static HttpResponseMessage GetAPIResponse(string url, string content)
{
StringBuilder traceLog = null;
HttpContent httpContent = null;
try
{
traceLog = new StringBuilder();
traceLog.AppendLine("Start: BusinessLayer getAPIResponse() Request Data:- " + DateTime.Now + "URL = " + url + "&content = " + httpContent);
using (HttpClient client = new HttpClient())
{
httpContent = new StringContent(content);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
var resp = client.PostAsync(url, httpContent).Result;
Debug.WriteLine("resp: " + resp.Content.ReadAsStringAsync().Result);
traceLog.AppendLine("End: BusinessLayer getAPIResponse() call completed HttpResponseMessage received");
return resp;
}
}
catch
{
throw;
}
finally
{
traceLog = null;
httpContent.Dispose();
url = string.Empty;
content = string.Empty;
}
}
In the following line, console prints the result that I cant understand where it cames from (Debug.WriteLine("resp: " + resp.Content.ReadAsStringAsync().Result);)
Sorry for the confusion , I am in my first job with zero work experience and I am called to learn how this works alone without proper education on ASP.NET from them.
You will not go very far without debbugger. Learn how to debug in Visual Studio (YouTube tutorials might be fastest way). Place debug points along critical points in code (for example moment when client sends and receives response is line var resp = client.PostAsync...) and check variables.
Url for API server is actually defined in the line
url = ConfigurationManager.AppSettings["login_url"].ToString();
ConfigurationManager means Web.config file, check it's appSettings section for login_url entry, there is your url.
Btw, using (HttpClient client = new HttpClient()) is not a good way to use a HttpClient and will lead to port exhaustion. It's ok for small number of requests, but for larger ones you must reuse it, or use HttpClientFactory (for .NET Core).
I need to get the results of google searches in order to loop through and parse them. With that aim in view, I followed (as best I could) the tutorial on how to do that here
This is my code, based on the sample/example code in the article referenced above:
private void btnRentFlick_Click(object sender, EventArgs e)
{
OpenBestPageForSearchString("rent amazon movie Will Penny");
}
private void OpenBestPageForSearchString(string searchStr)
{
try
{
const string apiKey = "blaBlaBla"; // "blaBlaBla" stands for my API key
const string searchEngineId = "bla"; // "bla" stands for various things I tried: my client_id
(also called UniqueId), private_key_id (also called KeyId), and project_id. Not having
the correct value may be the problem. If so, how do I get it?
const string query = "rent amazon movie Will Penny";
var customSearchService = new CustomsearchService(new BaseClientService.Initializer { ApiKey
= apiKey });
//CseResource.ListRequest listRequest = customSearchService.Cse.List(query); // This is the
code in the article, but it won't compile - "no overload for "List" takes one argument"
// So how is the value in "query" assigned, then?
CseResource.ListRequest listRequest = customSearchService.Cse.List();
listRequest.Cx = searchEngineId;
List<string> linksReturned = new List<string>();
IList<Result> paging = new List<Result>();
var count = 0; // I don't know what the purpose of the counting is, but I'll leave as-is
until I get it working at least
while (paging != null)
{
listRequest.Start = count * 10 + 1;
paging = listRequest.Execute().Items; // this takes several seconds, then it throws an
exception
if (paging != null)
{
foreach (var item in paging)
{
linksReturned.Add("Title : " + item.Title + Environment.NewLine + "Link : " +
item.Link +
Environment.NewLine + Environment.NewLine);
}
}
count++;
}
MessageBox.Show("Done with google amazon query");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
As the comment at the end of that line says, this line of code:
paging = listRequest.Execute().Items;
...works for several seconds, then throws an exception, namely this:
So what is causing this exception? Is it because the searchEngineId value I assigned is bad? Or is it because the search string (assigned to the query variable) has not been provided to the call?
The info about my Ids is contained in a .json file provided by google, and there is no "searchEngineId" value in it. This is what it does contain:
"type": "service_account", "project_id": "flix4famsasinlocator",
"private_key_id": "[my private key id]", "private_key": "-----BEGIN
PRIVATE KEY-----. . . PRIVATE KEY-----\n", "client_email":
"[bla].gserviceaccount.com", "client_id": "[my client Id]",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url":
"https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url":
"https://www.googleapis.com/robot/v1/metadata/x509/[bla]gserviceaccount.com"
So though the article previously mentioned purported to be, and at first appeared to be, just what the doctor ordered, I have ran into a wall of considerable dimensions. Does anybody know how to scale this wall - perhaps primarily by providing the search string to the CseResource.ListRequest object?
UPDATE
Trying DalmTo's code first, I used this (not showing his GetService() method, which I copied verbatim):
var query = "rent amazon movie Will Penny";
var service = GetService("theRainInSpainFallsMainlyOnTheDirt");
var request = service.Cse.List();
// add option values to the request here.
request.ExactTerms = query;
request.Q = query;
var response = request.ExecuteAsync();
// my contribution:
List<string> linksReturned = new List<string>();
foreach (var item in response.Result.Items)
{
//Console.WriteLine(item.Title);
// next two lines also mine
MessageBox.Show(string.Format("Title: {0}; Link: {1}; ETag: {2}", item.Title, item.Link, item.ETag));
linksReturned.Add(item.Link);
}
...but this exception was thrown while in the foreach loop:
UPDATE 2
Yes, this works (adapted from Trekco's answer):
const string apiKey = "gr8GooglyMoogly";
const string searchEngineId = "theRainInSpainFallsMainOnTheDirt";
const string query = "rent amazon movie Will Penny";
var customSearchService = new CustomsearchService(new BaseClientService.Initializer { ApiKey = apiKey });
CseResource.ListRequest listRequest = customSearchService.Cse.List();
listRequest.Cx = searchEngineId;
listRequest.Q = query;
List<string> linksReturned = new List<string>();
IList<Result> paging = new List<Result>();
var count = 0;
while (paging != null)
{
listRequest.Start = count * 10 + 1;
paging = listRequest.Execute().Items;
if (paging != null)
{
foreach (var item in paging)
{
linksReturned.Add(item.Link);
}
}
count++;
}
The query is not being send to google. To fix your code you need to tell the api what query to use. After listRequest.Cx = searchEngineId; add listRequest.Q = query;
var count = 0;
string apiKey = "THE API KEY";
string searchEngineId = "THE SEARCH ENGIN ID";
string query = "rent amazon movie Will Penny";
var customSearchService = new CustomsearchService(new BaseClientService.Initializer
{
ApiKey = apiKey
});
CseResource.ListRequest listRequest = customSearchService.Cse.List();
listRequest.Cx = searchEngineId;
listRequest.Q = query; // <---- Add this line
List<string> linksReturned = new List<string>();
while (count < 10) // Google limit you to 100 records
{
listRequest.Start = count * 10;
var paging = listRequest.Execute().Items;
foreach (var item in paging)
{
linksReturned.Add("Title : " + item.Title + Environment.NewLine + "Link : " +
item.Link +
Environment.NewLine + Environment.NewLine);
}
count++;
}
In your code you have a comment that you don't know what var count = 0; is for. It is to keep track on how many items you have requested.
If you look at google's documentation you will see that they will only return 100 results max. After that they will give you a error. That error will also be the same generic message: "INVALID_ARGUMENT"
You can review the custom search api requirements here: https://developers.google.com/custom-search/v1/reference/rest/v1/cse/list
The searchEngineId variable is the search Engine id that you generate on the site https://www.google.com/cse/all. The documentation you followed is a bit out of date. you will find the id here:
If you check the doucmntation cse.list I think you will find that the list method has no required fields which means that you need to add the option values in the following manner.
I think ExactTerms may be the one you are looking for. But it could also be Q i think you should read though the option values and decide which one is best for your purpose.
var query = "rent amazon movie Will Penny";
var service = GetService("MYKEY");
var request = service.Cse.List();
// add option values to the request here.
request.ExactTerms = query;
request.Q = query;
var response = request.ExecuteAsync();
foreach (var item in response.Result.Items)
{
Console.WriteLine(item.Title);
}
My get service method
public static CustomsearchService GetService(string apiKey)
{
try
{
if (string.IsNullOrEmpty(apiKey))
throw new ArgumentNullException("api Key");
return new CustomsearchService(new BaseClientService.Initializer()
{
ApiKey = apiKey,
ApplicationName = string.Format("{0} API key example", System.Diagnostics.Process.GetCurrentProcess().ProcessName),
});
}
catch (Exception ex)
{
throw new Exception("Failed to create new Customsearch Service", ex);
}
}
I am using "Kentor.AuthServices.dll" and "Kentor.AuthServices.Mvc.dll" in my code to allowing Single sign on with ADFS server and it is working fine but the problem is that it is taking around more than 1 min show the adfs login screen.
I have debugged the code and record the timing and found the all the code working fine but identity provider creating code is taking more than 1 min.
I am not able to understand why it is taking too much time.
I am putting my code below can anyone please help?
thanks in advance.
try
{
CommonUtility.LogMessage("Start at:" + DateTime.Now);
string adfsUrl = System.Configuration.ConfigurationManager.AppSettings["ADServer"] ?? "";
if(string.IsNullOrEmpty(adfsUrl))
{
CommonUtility.LogMessage("no adfs server found in config");
return RedirectToAction("Login", "Account", string.Empty);
}
string requestUrlScheme = System.Configuration.ConfigurationManager.AppSettings["ADInstance"] ?? "https";
string federationUrl = System.Configuration.ConfigurationManager.AppSettings["ADFSMetaData"] ?? "";
CommonUtility.LogMessage("metdaDataUrl=" + federationUrl);
string trustUrl = string.Format("{0}/adfs/services/trust", adfsUrl);
CommonUtility.LogMessage("trustURL=" + trustUrl);
var idps = Kentor.AuthServices.Mvc.AuthServicesController.Options.IdentityProviders.KnownIdentityProviders;
foreach (var idpItem in idps)
{
CommonUtility.LogMessage("existing ENtity ID=" + idpItem.EntityId.Id);
if (idpItem.EntityId.Id.Equals(trustUrl))
{
Kentor.AuthServices.Mvc.AuthServicesController.Options.IdentityProviders.Remove(idpItem.EntityId);
CommonUtility.LogMessage("removed existing entity at:" + DateTime.Now);
}
}
var spOptions = CreateSPOptions(requestUrlScheme);
CommonUtility.LogMessage("SP option created at:" + DateTime.Now);
Kentor.AuthServices.IdentityProvider idp = null;
**idp = new Kentor.AuthServices.IdentityProvider(new EntityId(trustUrl), spOptions)
{
AllowUnsolicitedAuthnResponse = true,
LoadMetadata = true,
MetadataLocation = federationUrl,
};**
CommonUtility.LogMessage("idp added at:" + DateTime.Now);
if (Kentor.AuthServices.Mvc.AuthServicesController.Options.SPOptions.EntityId == null)
Kentor.AuthServices.Mvc.AuthServicesController.Options.SPOptions.EntityId = new EntityId(string.Concat(string.Format("{0}://{1}{2}", requestUrlScheme, Request.Url.Authority, Url.Content("~")), "AuthServices"));
else
Kentor.AuthServices.Mvc.AuthServicesController.Options.SPOptions.EntityId.Id =
string.Concat(string.Format("{0}://{1}{2}", requestUrlScheme, Request.Url.Authority, Url.Content("~")), "AuthServices");
CommonUtility.LogMessage("AuthServicesURL=" + string.Concat(string.Format("{0}://{1}{2}", requestUrlScheme, Request.Url.Authority, Url.Content("~")), "AuthServices"));
Kentor.AuthServices.Mvc.AuthServicesController.Options.SPOptions.ReturnUrl =
new Uri(string.Concat(string.Format("{0}://{1}{2}", requestUrlScheme, Request.Url.Authority, Url.Content("~")), "SAMLAuthentication/SAMLResponse"));
CommonUtility.LogMessage("SAMLResponseURL=" + string.Concat(string.Format("{0}://{1}{2}", requestUrlScheme, Request.Url.Authority, Url.Content("~")), "SAMLAuthentication/SAMLResponse"));
Kentor.AuthServices.Mvc.AuthServicesController.Options.IdentityProviders.Add(idp);
CommonUtility.LogMessage("redirect times:" + DateTime.Now);
return RedirectToAction("SignIn", "AuthServices", new { idp = trustUrl });
}
catch (Exception ex)
{
CommonUtility.LogException(ex);
throw ex;
}
When you use "LoadMetadata", the IdentityProvider object will load the metadata from the remote address at construction time. If I remember correctly, that's done synchronously to be able to report errors back as an exception. Does it take time (or give a timeout) to download the metadata?
I have an asp.net mvc application were i send sms messages with URL to clients. message and URL is sent correctly but when i click on the link it does not open correctly, example there is no data passed from database, example if you click the following url, there is no data passed to view: http://binvoicing.com/InvoiceAddlines/PaymentPreview?originalId=11&total=585.00
Here code:
public ActionResult SendSms(string cellnumber, int? id, string rt, string tenant, decimal? total, string userloggedin)
{
StreamReader objReader;
WebClient client = new WebClient();
int payid = 0;
int paypalaid = 0;
string UrL = "";
string pass = "mypassword";
//string cell = cellnumber;
string user = "username";
var pay = from e in db.PayfastGateways
where e.userId == userloggedin
select e;
var paya = pay.ToList();
foreach (var y in paya)
{
payid = y.ID;
}
var pal = from e in db.PaypalGateways
where e.userId == userloggedin
select e;
var payla = pal.ToList();
foreach (var y in payla)
{
paypalaid = y.ID;
}
string url = Url.Action("PaymentPreview", "InvoiceAddlines", new System.Web.Routing.RouteValueDictionary(new { originalId = id, total = total }), "http", Request.Url.Host);
if (payid == 0 && paypalaid == 0)
{
UrL = "";
}
else
{
UrL = url;
}
string mess = " Dear Customer, please click on the following link to view generated invoice, you can also pay your invoice online." + UrL;
string message = HttpUtility.UrlEncode(mess, System.Text.Encoding.GetEncoding("ISO-8859-1"));
string baseurl =
"http://bulksms.2way.co.za/eapi/submission/send_sms/2/2.0?" +
"username=" + user + "&" +
"password=" + pass + "&" +
"message=" + message + "&" +
"msisdn=" + cellnumber;
WebRequest wrGETURL;
wrGETURL = WebRequest.Create(baseurl);
HttpUtility.UrlEncode("http://www.vcskicks.com/c#");
try
{
Stream objStream;
objStream = wrGETURL.GetResponse().GetResponseStream();
objReader = new StreamReader(objStream);
objReader.Close();
}
catch (Exception ex)
{
ex.ToString();
}
ViewBag.cellnumber = cellnumber;
ViewBag.id = id;
ViewBag.rt = rt;
ViewBag.tenant = tenant;
ViewBag.total = total;
ViewBag.UrL = UrL;
return View();
}
SMS send url like http://binvoicing.com/InvoiceAddlines/PaymentPreview?originalId=11&total=585.00
Here Is my PaymentPreview method:
public ActionResult PaymentPreview(int? originalId, decimal? total)
{
TempData["keyEditId"] = originalId;
ViewBag.ind = originalId;
decimal totals = 0;
totals = (decimal)total;
var line = from e in db.InvoiceAddlines
where e.AddlineID == originalId
select e;
var addlines = line.ToList();
foreach (var y in addlines)
{
decimal? de = Math.Round(totals);
string tots = de.ToString();
y.Total = tots;
db.SaveChanges();
}
return View(db.InvoiceAddlines.ToList());
}
Hope someone can assist, thanks.
I think there is something wrong with the way URL is being built. See if this works -
Change this part of your code
string url = Url.Action("PaymentPreview", "InvoiceAddlines", new System.Web.Routing.RouteValueDictionary(new { originalId = id, total = total }), "http", Request.Url.Host);
To
string url = Url.Action("PaymentPreview", "InvoiceAddlines", new { originalId = id, total = total })
I've set up the IPN to communicate with my website within Paypal, but for some reason paypal does not seem to call it. Below is the method that is listening, but its does not seem to get anything.
Could someone please point me in the write direction?
Thanks
[HttpPost]
public void paypalipn(string receiver_email, string receiver_id, string test_ipn, string txn_id, string payer_id, string payer_status, string payment_date, string payment_status, string payment_type)
{
string subject = "Audit - Paypal IPN ";
string buildemail = "receiver_email: " + receiver_email;
buildemail += "receiver_id: "+receiver_id;
buildemail += "<br>test_ipn: "+test_ipn;
buildemail += "<br>txn_id: " + txn_id;
buildemail += "<br>payer_id: " + payer_id;
buildemail += "<br>payer_status: " + payer_status;
buildemail += "<br>payment_date: " + payment_date;
buildemail += "<br>payment_status: " + payment_status;
buildemail += "<br>payment_type: " + payment_type;
Libraries.Email.Product.SendAudit(subject, buildemail);
}
If you are setting your IPN in your PayPal account, make sure that it is enabled and that the URL is correct. Also, if you are setting it in your account you can check your IPN history to see if the IPN POSTs are being sent out. They will either be marked as sent, retrying, or failed. If they are in a failed or retrying status you can click the message and if your server is sending back any error code it should be listed here. Also, check your error logs on your server to make sure the script is not erroring out.
I did something like this:
public class IPNData
{
public string Response { get; set; }
public NameValueCollection Args { get; set; }
}
Then a method for collecting data from the request, and sends the data to Paypal for verification.
IPNData GetIPNData()
{
var ipnData = new IPNData();
var param = Request.BinaryRead(HttpContext.Request.ContentLength);
var ipnStr = Encoding.ASCII.GetString(param);
ipnData.Args = HttpUtility.ParseQueryString(ipnStr);
// Return the ipn string to paypal for validation
ipnStr += "&cmd=_notify-validate";
var request = (HttpWebRequest)WebRequest.Create("https://www.paypal.com/cgi-bin/webscr");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = strRequest.Length;
using (var sw = new StreamWriter(request.GetRequestStream(), Encoding.ASCII))
{
sw.Write(ipnStr);
}
using (var sr = new StreamReader(request.GetResponse().GetResponseStream()))
{
// Response should be "VERIFIED"
ipnData.Response = sr.ReadToEnd();
}
return ipnData;
}
PaymentController.cs example for a subscriptionpayment, or if a user cancel a subscription.
public ActionResult PaypalIPNExample()
{
var ipn = GetIPNData();
if (ipn.Response != "VERIFIED")
{
// Do some logging
return null;
}
var type = ipn.Args["txn_type"];
var email = ipn.Args["payer_email"];
var transactionId = ipn.Args["txn_id"];
switch (type)
{
case "subscr_cancel":
UserService.CancelSubscription(email);
break;
case "subscr_payment":
if (ipn.Args["payment_status"].Equals("Completed"))
{
LogPayment(email, transactionId);
UserService.ExtendMembership(email);
}
break;
default:
// Do some logging?
break;
}
return Json("ok");
}
When I was debugging PayPal IPN responses, I did something like this:
string keysReceived = "";
foreach (string key in Request.Params.AllKeys)
keysReceived += "\r\nKey: " + key + ", Val: " + Request.Params[key];
string debugLogPath = HttpContext.Server.MapPath("/") + "debug_PayPalNotify.log";
System.IO.File.AppendAllText(debugLogPath, keysReceived);
Note the use of the global object Request. You can do a lot with that for debugging.