SagePay Direct Payment Integration C# - c#

I am trying to implement a credit card payment solution on my website using SagePay, where I can take payment on my website. I am using ASP.NET Web forms and C#. Here is my code:
var objSagePay = new SagePayIntegration();
var request = objSagePay.DirectPaymentRequest();
if ((request != null)) {
request.Vendor = "testVendor";
request.CardHolder = "Customer Name";
request.CardNumber = "4900000000000";
request.CardType = CardType.VISA;
request.ExpiryDate = "0119";
request.Cv2 = "123";
request.Currency = "GBP";
request.Amount = 10.0;
request.BillingAddress1 = "Test Address 1";
request.BillingAddress2 = "";
request.BillingPostCode = "412";
request.BillingCountry = "";
}
var result = objSagePay.ProcessDirectPaymentRequest(request, "https://test.sagepay.com/gateway/service/vspdirect-register.vsp");
When the result object call is executed, I get Object reference is Null.
Any idea where i am doing things wrong?
Stack Trace
[NullReferenceException: Object reference not set to an instance of an object.]
SagePay.IntegrationKit.SagePayIntegration.GetPropertyTextValue(Object request, String propertyName) in C:\dev\dotnet\VspDotNetKitAPI\SagePayIntegration.cs:93
SagePay.IntegrationKit.SagePayIntegration.ProcessDirectPaymentRequest(IDirectPayment paymentRequest, String directPaymentUrl) in C:\dev\dotnet\VspDotNetKitAPI\SagePayIntegration.cs:449
orders_payment_Default.btnProceedCreditCard_Click(Object sender, EventArgs e) in Default.aspx.cs:93
System.Web.UI.WebControls.Button.OnClick(EventArgs e) +9692746
System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +108
System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +12
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +15
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +35
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3562

You aren't setting enough properties on your payment request so it is throwing the NullReferenceException when trying to build the request object internally.
You can check if you have set at least the minimum values by calling the Validation method:
var errors = objSagePay.Validation(SagePay.IntegrationKit.ProtocolMessage.DIRECT_PAYMENT,
typeof(SagePay.IntegrationKit.Messages.IDirectPayment),
request,
SagePay.IntegrationKit.ProtocolVersion.V_300);
The errors object in this case will tell you that you are missing the following value:
VendorTxCode
This is your transaction identifier, for example, an order number. It needs to be a unique value for every payment you make. If you set that value, the error should go away.
Bonus: If you get really stuck with the SagePay Integration Kit for .Net, you can see the source code for it in my GitHub repository.

Related

Prevent out of memory error when writing too much to the browser

I got assigned the task of resolving a problem where I suspect too much data is attempting to be written to the browser. I.e Building tables to display on 2,000+ records.
$exception {"Exception of type 'System.OutOfMemoryException' was thrown."} System.Exception {System.OutOfMemoryException}
Exception is thrown on Page_PreRender
What is the easiest way to troubleshoot the problem?
What is the easiest way to test/resolve it?
Thanks
[OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.]
System.String.Concat(String str0, String str1, String str2, String str3) +76
ProgramName.File.GetData() in C:\inetpub\wwwroot\ProgramName\File.aspx.cs:137
ProgramName.File.Page_PreRender(Object sender, EventArgs e) in C:\inetpub\wwwroot\ProgramName\File.aspx.cs:18
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
System.Web.UI.Control.OnPreRender(EventArgs e) +8775110
System.Web.UI.Control.PreRenderRecursiveInternal() +80
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +842
With the stack trace I think I know your problem.
In your Page_PreRender method you are concatenating strings (you mention that you are constructing a table - it's likely that it's the code doing this).
If you concatenate 2 strings together, memory get's allocated to create a new string to hold the result, but the memory to store the first two strings does not get reclaimed because those strings are still in scope. I'm guessing that you are concatenating a lot of strings (in a loop), and thus are running out of memory.
The fix is to use a StringBuilder.
Find the code that looks something like this:
public void GetData()
{
string myTableString = "";
foreach (var row in MyRows)
{
myTableString += "<tr><td>" + row.someProperty + "</td></tr>"
}
to the following
using System.Text // This goes at the top of the file, with the other using statements.
...
public void GetData()
{
StringBuilder sb = new StringBuilder();
foreach (var row in MyRows)
{
sb.Append("<tr><td>" + row.someProperty + "</td></tr>");
}
string myTableString = sb.ToString();
Note that the code I've given above is just my best guess at what your code looks like - it would be much easier if you posted your code!!

NullReferenceException on 2nd Page_Load

At first I'd like to say: Yes I know that there are many Questions that are similar to mine, but not the same.
When I start one of my 12 sites on my developer-machine everything works wonderful, and also on the server 11 of them work without a problem.
When I start the 12th site it first works fine, but when it cause a postback (Button, DropDownList with AutoPostBack, etc... ) I get the following error:
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[NullReferenceException: Object reference not set to an instance of an object.]
Infoscreen.Anzeigeeinstellungen.Page_Load(Object sender, EventArgs e) in C:\Users\Krusty\Desktop\Schule\Diplomarbeit\Infoscreen\Infoscreen\Anzeigeeinstellungen.aspx.cs:97
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +24
System.Web.UI.Control.LoadRecursive() +70
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3047
the path (C:\Users\Krusty\Desktop\Schule\Diplomarbeit\Infoscreen\Infoscreen\Anzeigeeinstellungen.aspx.cs) is the one where the file was on my developer-machine.
but why??
I never hardcoded any path in my program, and even recreating the site didn't work.
What shall i do? Any tips/hints would be appreciated.
EDIT:
91 if (!Page.IsPostBack)
92 {
93 Response.Cookies["Infoscreen_Anzeigeeinstellungen_Ausgewählte_Abteilung"].Value = ausgewählte_Abteilung.ToString();
94 }
95 else
96 {
97 ausgewählte_Abteilung = Request.Cookies["Infoscreen_Anzeigeeinstellungen_Ausgewählte_Abteilung"].Value;
98 }
EDIT:
Yes, IIS is configured to use Cookies
EDIT:
SOLVED!
in VisualStudio2010 Server the char 'ä' works...
in IIS7 it doesn't...
so the cookie never gets set propperly and the get request hangs up
named the cookie "Infoscreen_Anzeigeeinstellungen_Ausgewaehlte_Abteilung" and it works fine now
can be closed
As you already found out your self but just for future reference:
In your code for handling the cookie the 'name' is allowed in c# (using a-umlaut) but as per RFC2616 the token for a cookie MUST contain a subset of US-ASCII chars.
if (!Page.IsPostBack)
{
Response.Cookies["Infoscreen_Anzeigeeinstellungen_Ausgewählte_Abteilung"].Value = ausgewählte_Abteilung.ToString();
}
else
{
ausgewählte_Abteilung = Request.Cookies["Infoscreen_Anzeigeeinstellungen_Ausgewählte_Abteilung"].Value;
}
So a way to have a safe Cookies key in case your cookiekey is generated based on form/controlnames could be:
static string TokenRFC2616(string key)
{
const string separators = "()|<>#,;:\\\"/[]?={} ";
var chars = from ch in key.Normalize(NormalizationForm.FormD)
where CharUnicodeInfo.GetUnicodeCategory(ch)
!= UnicodeCategory.NonSpacingMark &&
separators.IndexOf(ch)==-1
select ch;
return String.Concat(chars);
}
string cookiekey = TokenRFC2616(
"Infoscreen_Anzeigeeinstellungen_Ausgewählte_Abteilung");
if (!Page.IsPostBack)
{
Response.Cookies[cookieKey].Value = ausgewählte_Abteilung.ToString();
}
else
{
ausgewählte_Abteilung = Request.Cookies[cookieKey].Value;
}
(in the above sample the cookie name will be Infoscreen_Anzeigeeinstellungen_Ausgewahlte_Abteilung
)

System.ApplicationException

I am trying to rum my application and I am getting the following error as :
System.Web.HttpUnhandledException: Exception of type 'System.Web.HttpUnhandledException' was thrown.
The exception is thrown near the ** line of code:
public void LoadFromEntity(bool editable, string TabKey)
{
//Getting the FormMaster collection
**FormTemplate formTemplate = PolicyClassCollection.CachedPolicyClasses.FindBy((int)EnumPolicyClasses.PNI).FormTemplateCo**llection.Find(ft => ft.PolicyClassId == Utility.GetCurrentPolicyClassId() && ft.DocumentType.DocumentTypeId == (int)EnumDocumentTypes.Coverage_Summary && ft.PolicyTypeId == Utility.GetCurrentAccount().CurrentRisk.PolicyTypeId);
if (formTemplate != null)
{
//Set context string with current option number
this._Account.CurrentRisk.FormContextData = this.OptionNum.ToString();
//getting FormMasterID
Guid vsDatabaseId = formTemplate.FormFilingHistoryId;
string accountXmlString = this._Account.ToXML();
//Setting the parameters in PDFServiceParms class that are to be used in "PDFService.aspx" page.
PDFServiceParms pdfParams = new PDFServiceParms(FORM_MODE_EDIT, vsDatabaseId.ToString(), Model.AppConstants.FORM_TYPE_SELECTED_FORM, accountXmlString);
//Saving the parameters in the session. PDFService.aspx page reads the parameters from the session. Session key is passed in the
//query string when calling the PDFService.aspx page.
Session[AppConstants.SK_SUMMARY_PDF_PARAMS] = pdfParams;
//Setting the iFrame's source to PDFService.aspx page. The PDF document generated in this page is displayed in the iFrame.
this.iframePdf.Attributes["src"] = ResolveClientUrl(AppConstants.PAGE_NAME_PDFSERVICE) + "?datakey=" + AppConstants.SK_SUMMARY_PDF_PARAMS;
}
else
throw new ApplicationException("FormMaster not found for PolicyClass = " + Utility.GetCurrentPolicyClassId().ToString() + " and DocumentType = " + ((int)EnumDocumentTypes.Coverage_Summary).ToString());
}
Exception thrown:
System.Web.HttpUnhandledException: Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.ApplicationException: FormMaster not found for PolicyClass = 2 and DocumentType = 27
at PNI_SqbpeCovInfoPNISummary.LoadFromEntity(Boolean editable, String TabKey) in C:\TFS\Navigate Development\NavigateWebApp\PNI\SqbpeCovInfoPNISummary.aspx.cs:line 95
at SQBPECoverageInformationMasterPNI.LoadFromEntity() in C:\TFS\Navigate Development\NavigateWebApp\PNI\SQBPECoverageInformationMasterPNI.master.cs:line 188
at SQBPE.Page_Load(Object sender, EventArgs e) in C:\TFS\Navigate Development\NavigateWebApp\SQBPE.master.cs:line 55
at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
at System.Web.UI.Control.OnLoad(EventArgs e)
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
--- End of inner exception stack trace ---
at System.Web.UI.Page.HandleError(Exception e)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest()
at System.Web.UI.Page.ProcessRequest(HttpContext context)
at ASP.pni_sqbpecovinfopnisummary_aspx.ProcessRequest(HttpContext context) in c:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET Files\navigatewebapp\253cae21\57ec5e1d\App_Web_sqbpecovinfopnisummary.aspx.41d7eb59.1z9y4p0a.0.cs:line 0
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
can some one please let me know what need to be done for this.
Sorry, edit of whole answer, previous was only halfway correct
The parent exception is a HttpUnhandledException. The internal exception seems quite clear and says:
FormMaster not found for PolicyClass = 2 and DocumentType = 27
That error is in your own code. The ApplicationException is not happening on the line you are referring to. The result of that line is that formTemplateis null and your code throws this exception.
This is the line throwing the exception:
throw new ApplicationException("FormMaster not found for PolicyClass = "
+ Utility.GetCurrentPolicyClassId().ToString()
+ " and DocumentType = "
+ ((int)EnumDocumentTypes.Coverage_Summary).ToString());
(a friendly tip, use string.Format instead)
And this is the line returning null:
FormTemplate formTemplate = PolicyClassCollection.CachedPolicyClasses
.FindBy((int)EnumPolicyClasses.PNI).FormTemplateCollection
.Find(ft => ft.PolicyClassId == Utility.GetCurrentPolicyClassId()
&& ft.DocumentType.DocumentTypeId == (int)EnumDocumentTypes.Coverage_Summary
&& ft.PolicyTypeId == Utility.GetCurrentAccount().CurrentRisk.PolicyTypeId);
(a friendly tip: write it out over multiple lines. That helps with setting breakpoints and with readability)
Your next question should be: why is it returning null? The answer, I don't know. In my previous attempt of answering I said something about third party code. And that's exactly what this is, as the class PolicyClassCollection is not a well-known class, there's no documentation on the internet on it. So either it is your own, in which case you can try stepping through (set a breakpoint) or it is someone else's in which case you can try calling the vendor or try stepping through after removing the "just my code" setting.

Subsonic 3.0.0.4 ActiveRecord Template for MySQL error on inserting new record

public void Add(IDataProvider provider){
var key=KeyValue();
if(key==null){
var newKey=_repo.Add(this,provider);
this.SetKeyValue(newKey);
}else{
_repo.Add(this,provider); //NullReferenceException was unhandled by user code
}
SetIsNew(false);
OnSaved();
}
'this' contains
this
{Geocine}
_age: null
_birthday: null
_church_id: null
_db: {Seminary.Data.SeminaryDB}
_dirtyColumns: Count = 0
_finalgrade: null
_finalgrade_equivalent: null
_first_name: "Geocine"
_gender: null
_isLoaded: false
_isNew: true
_last_name: "Cruz"
_level: null
_middle_name: "Reilly"
_repo: {SubSonic.Repository.SubSonicRepository<Seminary.Data.student>}
_semester_enrolled: null
_seminary_id: null
_student_id: 0
_year_enrolled: null
age: null
birthday: null
church_id: null
Columns: Count = 14
finalgrade: null
finalgrade_equivalent: null
first_name: "Geocine"
gender: null
last_name: "Cruz"
level: null
middle_name: "Reilly"
semester_enrolled: null
seminary_id: null
student_id: 0
tbl: {student}
TestMode: false
year_enrolled: null
provider contains
provider
{SubSonic.DataProviders.DbDataProvider}
[SubSonic.DataProviders.DbDataProvider]: {SubSonic.DataProviders.DbDataProvider}
Client: MySqlClient
ConnectionString: "Data Source=localhost;Database=school;User Id=root;Password=123456;Port=3306;"
CurrentSharedConnection: null
DbDataProviderName: "MySql.Data.MySqlClient"
Factory: {MySql.Data.MySqlClient.MySqlClientFactory}
Log: null
Name: "MySql.Data.MySqlClient"
ParameterPrefix: "#"
Schema: {SubSonic.Schema.DatabaseSchema}
SchemaGenerator: {SubSonic.SqlGeneration.Schema.MySqlSchema}
Here is the stacktrace
[NullReferenceException: Object reference not set to an instance of an object.]
MySql.Data.MySqlClient.MySqlConnection.get_ServerThread() +6
MySql.Data.MySqlClient.MySqlConnection.Abort() +54
MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior) +839
MySql.Data.MySqlClient.MySqlCommand.ExecuteDbDataReader(CommandBehavior behavior) +4
System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior) +10
SubSonic.DataProviders.DbDataProvider.ExecuteReader(QueryCommand qry) +175
SubSonic.Repository.SubSonicRepository`1.Add(T item, IDataProvider provider) +165
Seminary.Data.student.Add(IDataProvider provider) in C:\Users\SomeUser\Documents\Visual Studio 2008\Projects\Seminary\ActiveRecord\ActiveRecord.cs:2490
Seminary.Data.student.Save(IDataProvider provider) in C:\Users\SomeUser\Documents\Visual Studio 2008\Projects\Seminary\ActiveRecord\ActiveRecord.cs:2505
Seminary.Data.student.Save() in C:\Users\SomeUser\Documents\Visual Studio 2008\Projects\Seminary\ActiveRecord\ActiveRecord.cs:2499
Seminary.Default.btnAdd_Click(Object sender, EventArgs e) in C:\Users\SomeUser\Documents\Visual Studio 2008\Projects\Seminary\Default.aspx.cs:34
System.Web.UI.WebControls.Button.OnClick(EventArgs e) +111
System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +110
System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +36
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1565
Here is the code that called the error:
student studentObject = new student();
studentObject.first_name = txtFirstName.Text;
studentObject.middle_name = txtMiddleName.Text;
studentObject.last_name = txtLastName.Text;
studentObject.Save();
That is a bit tricky. This exceptions happens with the current version of mysql.connector.net.
Normally an exception would be trown at this point, but the connector seems to have an NullReferenceException itself before it can throw the actual exception.
The "real" exception could be anything from "DUPLICATE KEY ..." to "Field XYZ does not have a default value" or "You have an error in your SQL Syntax near ..."
I haven't had time yet to figure out why this happens (debug the Connector.Net or try a newer one) but in the mean time I would suggest you do the following as I do:
Download unix tools for windows: http://unxutils.sourceforge.net/ and put them in the path (we need the tail command)
Configure mysql to write a query.log to c:\temp
[mysqld]
log=c:/temp/query.log
Start a console and type
tail -f c:\temp\query.log
Now you see every statement that is executed against your local database and if you get the NullReferenceException copy the last statement form the console window to a mysql query browser instance and execute it there.
Hope that helps, I will update this post if I figured out how to fix this issue.

Caching not working with IIS?

All,
I have an ASP.NET(C#) that functions as expected with the integrated debugger/web server. However when I move it over to a IIS server it appears as though the cache object is not being set. Can anyone offer any help?
Here is the class that sets the cache and subsequent cookie.
class globals
{
public NameValueCollection values;
private static string m_visitNumber ="";
public globals()
{
string userName = HttpContext.Current.Request.Cookies["PatientDischargeSummary"].Value;
values = HttpContext.Current.Cache[userName] as NameValueCollection;
}
public globals(NameValueCollection form)
{
// Copy the form values.
values = new NameValueCollection();
values.Add("txtCR", form["txtCR"]);
values.Add("txtName", form["txtName"]);
// Add the values to the cache.
//HttpContext.Current.Cache.Insert(form["txtUserName"], values, null, System.Web.Caching.Cache.NoSlidingExpiration, TimeSpan.FromMinutes(5));
HttpRuntime.Cache.Insert(form["txtUserName"], values, null, DateTime.Now.AddMinutes(5), System.Web.Caching.Cache.NoSlidingExpiration);
//HttpContext.Current.Cache.Insert(form["txtUserName"], values, null, DateTime.Now.AddMinutes(5), System.Web.Caching.Cache.NoSlidingExpiration);
// Add the username to the cookies.
HttpCookie cookie = new HttpCookie("PatientDischargeSummary", form["txtUserName"]);
cookie.Expires = DateTime.Now.AddMinutes(30);
cookie.HttpOnly = true;
HttpContext.Current.Response.Cookies.Add(cookie);
}
An example of me using the cache:
globals pcs;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
pcs = new globals();
lblActiveEditor.Text = pcs.values["txtName"];
}
}
Generate the following error under IIS:
[NullReferenceException: Object reference not set to an instance of an object.]
navigationtest.Demographics.Page_Load(Object sender, EventArgs e) in Demographics.ascx.cs:23
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +15
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +34
System.Web.UI.Control.OnLoad(EventArgs e) +99
System.Web.UI.Control.LoadRecursive() +47
System.Web.UI.Control.LoadRecursive() +131
System.Web.UI.Control.LoadRecursive() +131
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1061
Any thoughts?
pcs.values["txtName"]
That's null and it's already gone from Cache when you're trying to receive it. Your code seems to cache some per-request data obtained from users' input and there's nothing to guaranty the availability of that data in your cache.
Every cache access should be prepared to fetch the data from the data source in case of a miss, so, in your case I would use the user's session (although I'm not aware of your architecture, how many servers...) Using the user's session would persist that data for the life of the appdomain or the session itself (whichever ends first), so you should also be prepared to query it again in case of a miss / timeout / appdomain shutdown.
Should you be using HttpContext.Cache instead of HttpRuntime.Cache ?

Categories

Resources