Why is my object created on backend C# becoming null - c#

I'm using asp.net and c# for backend code and html, javascript/jquery on frontend
User clicks "Details" on website to view and edit requests previously created.
jquery/ajax calls method on backend to get infomation about requests.
An object, newWaferRequest, is created which holds this information. The object is returned from ajax call and the site populates a form with that information. The user can then edit the form, add new programs to requests, modify existing requests info etc...
The problem I'm getting is when the user selects "Save pgm", ajax calls backend savePgm method which is supposed to update the Object newWaferRequest previously created, but I'm receiving a nullReferenceException. The exception is pointing to the newWaferRequest object being null. This happens at different times when the user is updating the request. Sometimes the user can update the program and add new programs, with a correct response from backend. Other times the exception occurs.
I must not have a full grasp of how variables are "stored" when using the web. I read multiple post on here and have read about Session and ViewState variables. I've tried saving the Object in a Session with no luck.
This is just showing the beginning of my c# code, I tried using static variables initially. All the objects are in App_code cs files.
public partial class Nbump_Request : System.Web.UI.Page
{
//public static person currentPerson = new person();
//public static requestSearch searchRequest;
//public static waferRequest newWaferRequest;
//public static waferRequestObject newWaferRequestObject;
static person currentPerson = new person();
static requestSearch searchRequest;
static waferRequest newWaferRequest;
static waferRequestObject newWaferRequestObject;
Here is ajax method for existing requests, which creates objects
[WebMethod]
public static string queryRequestExisting(string request_pk)
{
JavaScriptSerializer js = new JavaScriptSerializer();
try
{
newWaferRequest = new waferRequest(request_pk, "EXISTINGREQUEST");
newWaferRequestObject = newWaferRequest.CURRENTREQUEST;
string json = js.Serialize(newWaferRequest);
return json;
}
catch (Exception)
{
return null;
} 
}
Here is ajax code for when user saves or updates program information. I added in the code to check and return with the object was null.
public static string savePgmData(Dictionary<string, string> pgm_requests)
{
PgmRequestObject currentPgm;
if (newWaferRequest != null)
{
try
{
//if (!Convert.ToBoolean(pgm_requests["pgmEdit"])) //not performed when request pgm being edited
string rtnMessage;
//create new pgm in waferRequest object
if (pgm_requests["PGMRT_INDEX_PK"] == null)
{
int index = newWaferRequest.addNewPGMRequest() - 1;
currentPgm = (PgmRequestObject)newWaferRequest.PGMREQUESTLIST[index];
string pgmPrimaryKey = currentPgm.PGMRT_INDEX_PK;
rtnMessage = "{\"message\": \"Added and saved new pgm successfully\", \"primaryKey\":\"" + pgmPrimaryKey + "\"}";
}
//get pgm to update at index provided
else if (pgm_requests["pgmRowIndex"] != "-1")
{
int index = Convert.ToInt32(pgm_requests["pgmRowIndex"]);
currentPgm = (PgmRequestObject)newWaferRequest.PGMREQUESTLIST[index];
rtnMessage = "Edited and saved pgm successfully";
}
//save initial pgm
else
{
currentPgm = (PgmRequestObject)newWaferRequest.PGMREQUESTLIST[0];
rtnMessage = "Initial pgm added successfully";
}
 
 
currentPgm.updatePGM(pgm_requests["pgmNameList"], pgm_requests["pgmNameText"]);
currentPgm.updateStatus(pgm_requests["pgmStatus"]);
currentPgm.updateWafers(pgm_requests["pgmWfrList"], pgm_requests["pgmWfrNum"]);
currentPgm.updatePriority(pgm_requests["pgmTestOrder"]);
currentPgm.updateFailBinRetest(pgm_requests["pgmFbr"], pgm_requests["pgmFbrBins"]);
//currentPgm.CommitIntoDatabase(); // -- Called on individual requests updates before request saved
 
return rtnMessage;
}
catch (Exception ex)
{
return "Failed to save program\n\n" + ex.Data + "\n" + ex.Message + "\n" + ex.StackTrace + "\n";
}
}
else
{
return "newWaferRequest object is null\n";
}
}
This is a short snippet of the class for waferRequest. This is located in the app_code and is a cs file. The pgmRequestList contains an array of pgm objects. That is what I update when user selects "Save Program".
public class waferRequest
{
/*The class will hold request information, creation and delete.
*
*/
private waferRequestObject currentRequest;
private ArrayList WaferRequestList = new ArrayList();
private ArrayList PGMRequestList = new ArrayList();
Here is an example of what I tried for Session. I got rid of static variables and modified the methods
[WebMethod(EnableSession=true)]
public static string queryRequestExisting(string request_pk)
{
waferRequest newWaferRequest;
waferRequestObject newWaferRequestObject;
JavaScriptSerializer js = new JavaScriptSerializer();
try
{
newWaferRequest = new waferRequest(request_pk, "EXISTINGREQUEST");
newWaferRequestObject = newWaferRequest.CURRENTREQUEST;
HttpContext.Current.Session["newWaferRequest"] = newWaferRequest;
HttpContext.Current.Session["newWaferRequestObject"] = newWaferRequestObject;
string json = js.Serialize(newWaferRequest);
return json;
}
catch (Exception)
{
return null;
} 
}
//snippet of savePgmData with session
public static string savePgmData(Dictionary<string, string> pgm_requests)
{
waferRequest newWaferRequest = HttpContext.Current.Session["newWaferRequest"];
PgmRequestObject currentPgm;
if (newWaferRequest != null)
{
try
{
//if (!Convert.ToBoolean(pgm_requests["pgmEdit"])) //not performed when request pgm being edited
string rtnMessage;
//create new pgm in waferRequest object
if (pgm_requests["PGMRT_INDEX_PK"] == null)
{
int index = newWaferRequest.addNewPGMRequest() - 1;
currentPgm = (PgmRequestObject)newWaferRequest.PGMREQUESTLIST[index];
I am limited to the code I'm allowed to show because of work security. Please let me know if more information is needed.
Also, the code seems to work fine on my local server. The issue is when I put it on the production server or development server -- Both of which I don't have access to make changes on.

Related

The endpoint for my Azure APIs (Translator Text, Computer Vision) is not accesible (error code 404)

I followed the Hololens Tutorials provided by Microsoft and encountered some problems regarding Azure services in 301 (https://learn.microsoft.com/en-us/windows/mixed-reality/mr-azure-301#chapter-4--setup-debug-canvas) and 302 (https://learn.microsoft.com/en-us/windows/mixed-reality/mr-azure-302). I think the problem has something to do with the endpoint, because the error code 404 appears when checking https://westeurope.api.cognitive.microsoft.com/.
I use the Hololens first generation, Unity 2017.4.27f1, HoloToolkit-Unity-Examples-2017.4.3.0 and Visual Studio Community 2017. I've tried some of the Hololens tutorials, which all worked fine with these versions. My code is the one provided by Microsoft for the Tutorials 301 and 302. I've changed the location in Azure from
'global' to 'Western Europe' by creating a new ressource group and have now https://westeurope.api.cognitive.microsoft.com/ as my endpoint, I also created new authentification keys for the APIs and updated them in my code.
Instead of myKey I inserted the first key of the respective API (Translator Text, Computer Vision). The code below is from Tutorial 302 and the class 'VisionManager.cs' (which seems to be the responsible one for the communication with the services of the Computer Vision API).
public static VisionManager instance;
// you must insert your service key here!
private string authorizationKey = "myKey";
private const string ocpApimSubscriptionKeyHeader = "Ocp-Apim-Subscription-Key";
private string visionAnalysisEndpoint = "https://westcentralus.api.cognitive.microsoft.com/vision/v2.0"; // This is where you need to update your endpoint, if you set your location to something other than west-us.
internal byte[] imageBytes;
internal string imagePath;
/// <summary>
/// Call the Computer Vision Service to submit the image.
/// </summary>
public IEnumerator AnalyseLastImageCaptured()
{
WWWForm webForm = new WWWForm();
using (UnityWebRequest unityWebRequest = UnityWebRequest.Post(visionAnalysisEndpoint, webForm))
{
// gets a byte array out of the saved image
imageBytes = GetImageAsByteArray(imagePath);
unityWebRequest.SetRequestHeader("Content-Type", "application/octet-stream");
unityWebRequest.SetRequestHeader(ocpApimSubscriptionKeyHeader, authorizationKey);
// the download handler will help receiving the analysis from Azure
unityWebRequest.downloadHandler = new DownloadHandlerBuffer();
// the upload handler will help uploading the byte array with the request
unityWebRequest.uploadHandler = new UploadHandlerRaw(imageBytes);
unityWebRequest.uploadHandler.contentType = "application/octet-stream";
yield return unityWebRequest.SendWebRequest();
long responseCode = unityWebRequest.responseCode;
try
{
string jsonResponse = null;
jsonResponse = unityWebRequest.downloadHandler.text;
// The response will be in Json format
// therefore it needs to be deserialized into the classes AnalysedObject and TagData
AnalysedObject analysedObject = new AnalysedObject();
analysedObject = JsonUtility.FromJson<AnalysedObject>(jsonResponse);
if (analysedObject.tags == null)
{
Debug.Log("analysedObject.tagData is null");
}
else
{
Dictionary<string, float> tagsDictionary = new Dictionary<string, float>();
foreach (TagData td in analysedObject.tags)
{
TagData tag = td as TagData;
tagsDictionary.Add(tag.name, tag.confidence);
}
ResultsLabel.instance.SetTagsToLastLabel(tagsDictionary);
}
}
catch (Exception exception)
{
Debug.Log("Json exception.Message: " + exception.Message);
}
yield return null;
}
}
[System.Serializable]
public class TagData
{
public string name;
public float confidence;
}
[System.Serializable]
public class AnalysedObject
{
public TagData[] tags;
public string requestId;
public object metadata;
}
// Use this for initialization
void Start () {
}
private void Awake()
{
// allows this instance to behave like a singleton
instance = this;
}
// Update is called once per frame
void Update () {
}
/// <summary>
/// Returns the contents of the specified file as a byte array.
/// </summary>
private static byte[] GetImageAsByteArray(string imageFilePath)
{
FileStream fileStream = new FileStream(imageFilePath, FileMode.Open, FileAccess.Read);
BinaryReader binaryReader = new BinaryReader(fileStream);
return binaryReader.ReadBytes((int)fileStream.Length);
}
I expected the output to be like the examples in the tutorials, but instead I got the same GUI results without any updates. In 301 I could see the same screen, but the text field 'You just said' and the 'Translation' never updated when I spoke. In 302 I could airtap and make a screenshot and could see at first 'Analyzing' and later on 'I see:' but without any results of detected objects. So it seems to me, that the Azure APIs services can't be contacted and I don't get any analysis data in return (probably you notice, that I'm quite new to the whole topic, so maybe my assumption is wrong).

How to cache in c#

I have a service method which is getting data from a URL based on the parameters news/blogs.
How to cache the data coming from the URL every 30 minutes?
The user details also get cached for 30 minutes.
Also how do i cache the news,blogs separately if they are coming from the same service URL
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class IITNews : IIITNews
{
System.Web.SessionState.HttpSessionState session = HttpContext.Current.Session;
private static DateTime cacheExpiry = DateTime.MinValue;
string loggedinUser = "";
private string cachedResponse = "";
public Stream getNewsBlogsZD(string type, string noOfItems, string devicetype)
{
try
{
if (cacheExpiry > DateTime.Now)
{
if (System.Web.HttpContext.Current.Cache[cachedResponse] != null)
{
logger.Debug(loggedinUser + "Getting the cached data");
}
return new MemoryStream(Encoding.UTF8.GetBytes(cachedResponse));
}
else
{
string loggedInUserNum = GetEmployeeNumber();
string scenarioType = "";
string url = "";
if (type.Trim().ToUpper() == "NEWS")
{
scenarioType = "DisplayNews";
url = ServiceURL + "getWidgetDetails?WName=News&noOfItems=" + Convert.ToInt32(noOfItems.Trim());
}
else if (type.Trim().ToUpper() == "ZD")
{
scenarioType = "DisplayZD";
url = ServiceURL + "getWidgetDetails?WName=ZD&noOfItems=" + Convert.ToInt32(noOfItems.Trim());
}
else if (type.Trim().ToUpper() == "BLOGS")
{
scenarioType = "DisplayBlogs";
url = ServiceURL + "getWidgetDetails?WName=Blogs&noOfItems=" + Convert.ToInt32(noOfItems.Trim());
}
WebClient client = new WebClient();
client.UseDefaultCredentials = true;
client.Encoding = System.Text.Encoding.UTF8;
cachedResponse = client.DownloadString(url);
HttpContext.Current.Cache.Insert("cacheResponse",cachedResponse ,null);
cacheExpiry = DateTime.Now.AddMinutes(30);
return new MemoryStream(Encoding.UTF8.GetBytes(cachedResponse));
}
}
catch (Exception ex)
{
string message=ex.message;
return new MemoryStream(Encoding.UTF8.GetBytes("[]"));
}
}
public stream userdertails
{
//method to fetch user details where no cache is used
}
}
If this is your service, you can cache it on the service and return same data for very same parameters.
If not, you can create some singleton class to hold data in. If the singleton has valid data, return them instead of calling WebService :)
Store the result somewhere, along with a time stamp. Where you store it is up to you. There are a variety of caching systems you can find, there's a database, there's the file system, in-memory static values, instance values, etc., etc.
Possibly the simplest approach would just be a class-level value. Something like this:
private string cachedResponse = "";
private DateTime cacheExpiry = DateTime.MinValue;
Then in your logic you would check for the cache before deciding to query the service. Something like this:
if (cacheExpiry > DateTime.Now)
return new MemoryStream(Encoding.UTF8.GetBytes(cachedResponse));
// the rest of your method to query the service
// then...
cachedResponse = client.DownloadString(url);
cacheExpiry = DateTime.Now.AddMinutes(30);
return new MemoryStream(Encoding.UTF8.GetBytes(cachedResponse));
This is just an example of the logic behind the concept of a cache, of course. If your object instance itself doesn't remain in memory then this object-level cache of course wouldn't do the job. The logic is always the same:
Check if the cache is still valid.
If so, return the cached value.
If not, query the service and store the new value and update the cache expiry and return the newly cached value.
Where you store the cache is up to you and depends on more than what's present in this question.
You can use the MemoryCache Class which enables you to cache objects and set time of them to live in cache.

Variable scoping c#

I am fairly new to c# and am getting an error "Object reference not set to an instance of an object." I am creating an XML packet and sending it to an external device for control. If I put the following code on the form in a click event it works beautifully.
On the btn Click event it looks like this:
SetTestInfoResponse testDataDs = null;
TestInformation testInfo = null;
this.PopulateTestDataXml();
string stringRequestXML = string.Empty;
string stringResponseXML = string.Empty;
//Creates Request packet
stringRequestXML = XMLCommunicationPackets.SetTestInformation (testInfo, testInfo.TestID, testInfo.TestUser, testInfo.TestSampleType, testInfo.TestSampleId, testInfo.TestMethodNumber, testInfo.TestTubeSn, testInfo.TestComments);
//Write set Test Info XML Packet and get response for ack or failure.
stringResponseXML = PluginContext.GetInstance().InstrumentDriverCurrent.GetInstrumentControl().SetCommonParameter(stringRequestXML);
However, If I move my entire function out of the form and try to call it when clicking a button I get the error.
written in a method off the form in a .cs file it reads:
public static SetTestInfoResponse SetTestData()
{
SetTestInfoResponse testDataDs = null;
TestInformation testInfo = null;
string stringRequestXML = string.Empty;
string stringResponseXML = string.Empty;
//Creates Request packet
stringRequestXML = XMLCommunicationPackets.SetTestInformation (testInfo, testInfo.TestID, testInfo.TestUser, testInfo.TestSampleType, testInfo.TestSampleId, testInfo.TestMethodNumber, testInfo.TestTubeSn, testInfo.TestComments);
//Write set Test Info XML Packet and get response for ack or failure.
stringResponseXML = PluginContext.GetInstance().InstrumentDriverCurrent.GetInstrumentControl().SetCommonParameter(stringRequestXML);
The error occurs when building stringRequestXml.
Part of my problem is the PopulateTestData() is a method on the form itself. Its purpose is to take data from txtboxes and cmbboxes and assign them to their respective arguments..
private TestInformation PopulateTestDataXml()
{
TestInformation UiTestData = new TestInformation();
UiTestData.TestID = txtTestId.Text;
UiTestData.TestUser = cmbUsers.SelectedItem.ToString();
UiTestData.TestSampleType = txtSampleType.Text;
UiTestData.TestSampleId = txtSampleId.Text;
UiTestData.TestMethodNumber = Convert.ToInt32(cmbMethod.SelectedItem);
UiTestData.TestTubeSn = txtTubeSerialNum.Text;
UiTestData.TestComments = txtComments.Text;
return UiTestData;
}
Here is the SetTestInformation() method where I am getting the error:
public static string SetTestInformation(TestInformation testInfo, string stringTestId, string stringUser, string stringSampleType, string stringSampleId, int intMethodNumber, string stringTubeSn, string stringComments)
{
try
{
string stringRequestXMLPacket = string.Empty;
string stringType = #"Request";
string stringCommand = #"Set";
string stringArgument = #"TestInformation";
CommunicationPacket requestXMLPacket = new CommunicationPacket(stringRootTag, stringXMLVersion, stringType, stringCommand);
requestXMLPacket.AddCommandArgument(stringArgument);
requestXMLPacket.AddArgumentItem(stringArgument, "sTestId", testInfo.TestID.ToString());
requestXMLPacket.AddArgumentItem(stringArgument, "sUser", testInfo.TestUser.ToString());
requestXMLPacket.AddArgumentItem(stringArgument, "sSampleType", testInfo.TestSampleType.ToString());
requestXMLPacket.AddArgumentItem(stringArgument, "sSampleId", testInfo.TestSampleId.ToString());
requestXMLPacket.AddArgumentItem(stringArgument, "nMethodNumber", testInfo.TestMethodNumber.ToString());
requestXMLPacket.AddArgumentItem(stringArgument, "sTubeSn", testInfo.TestTubeSn.ToString());
requestXMLPacket.AddArgumentItem(stringArgument, "sComments", testInfo.TestComments.ToString());
stringRequestXMLPacket = requestXMLPacket.CreateXMLPacket();
return stringRequestXMLPacket;
}
catch (Exception ex)
{
throw ex;
}
}
Iknow I am having trouble with the variable scope here. I still have to use the method PopulateTestDataXml on the form before I call the setTestData() method. But when I call the Method I have to declare testInfo = null or the parameters for SetTestInformation are not valid ("Does not exist in the current context"). What would I need to pass and how for this to work as a called method on the form btn click? I need to do this as I have alot of deserializing functions written as well to catch error messages in the response xml (these all work fine) and its just too much info on the click event. (And I need to learn).
Thanks
Neither of your examples should work (regardless of where you put them). This is simply incorrect:
TestInformation testInfo = null;
// ...
stringRequestXML = XMLCommunicationPackets.SetTestInformation (testInfo,
testInfo.TestID, ...);
// ^^ BANG!
Your testInfo object is null. When you try and access anything on a null object.. a NullReferenceException is thrown. You need to initialize it first. You're trying to do that in your PopulateTestDataXml method.. which returns the object your after. So change your code to this:
TestInformation testInfo = PopulateTestDataXml(); // assign it
Here is your problem..
public static SetTestInfoResponse SetTestData()
{
SetTestInfoResponse testDataDs = null;
TestInformation testInfo = null;
string stringRequestXML = string.Empty;
string stringResponseXML = string.Empty;
//Creates Request packet
stringRequestXML = XMLCommunicationPackets.SetTestInformation (testInfo, testInfo.TestID, testInfo.TestUser, testInfo.TestSampleType, testInfo.TestSampleId, testInfo.TestMethodNumber, testInfo.TestTubeSn, testInfo.TestComments);
//Write set Test Info XML Packet and get response for ack or failure.
stringResponseXML = PluginContext.GetInstance().InstrumentDriverCurrent.GetInstrumentControl().SetCommonParameter(stringRequestXML);
Are you assigning values for these objects I see they are just declared but never assigned.
SetTestInfoResponse testDataDs = null;
TestInformation testInfo = null;
i don't see you use null objects, so i'm wonder if you set them later, also u said the error happen on
private TestInformation PopulateTestDataXml()
{
TestInformation UiTestData = new TestInformation();
UiTestData.TestID = txtTestId.Text;
UiTestData.TestUser = cmbUsers.SelectedItem.ToString();
UiTestData.TestSampleType = txtSampleType.Text;
UiTestData.TestSampleId = txtSampleId.Text;
UiTestData.TestMethodNumber = Convert.ToInt32(cmbMethod.SelectedItem);
UiTestData.TestTubeSn = txtTubeSerialNum.Text;
UiTestData.TestComments = txtComments.Text;
return UiTestData;
}
after moving it out of your form, which mean possibly it's text box references is broken...
so what you can do, is store a pointer, like in your program.cs where you call your form to show up,
you can create an static object of form, and then put it in your class, then set it in program.cs file like :
Form1 f=new Form();
MyClass.staticFormPointer = f;
and also replace (new Form()), with (f) on the calling method,
your my class is like this:
class MyClass{
public static Form1 staticFormPointer = null;
//your code
.
.
.
// and in your methods you call it like this txtBox1.Text -> staticFormPointer.txtBox1.Text
}

Null values gathering data for Aspose Dynamic Slide Generation CRM 2011

I am having with using Aspose to generate dynamic content in slides within Microsoft CRM Dynamics 2011. The data is not populating correctly for several fields and relationals even though the logic in the code seems to be correct and should not yield a null or empty value, and I have confirmed there is indeed data for the fields in the database (The data does populate correctly for some of the fields and relationals). All of these issues occur before the powerpoint itself even starts to be generated, so in reality the issues may not be “Aspose” issues they may just be Web Service / CRM issues with retrieving the data asynchronously.
Aspose Slide Workflow:
1) An HTML web resource includes a Silverlight button to download powerpoint report
2) On button click the Silverlight application Asyncronosously collects all the data needed from the Project entity in CRM through web service requests
3) The data is compiled into a Project class that is then passed over to the ReportGenerator Service and uses the data to populate the parts of the powerpoint (This is the part where we use the custom Aspose stuff)
4) Aspose functionality goes through each specified slide and parses them adding in the data where required.
5) Powerpoint is completed and spit out for the user with the data populated.
These are two examples of where I am having troubles getting data to populate. The project.Pwins value below ends up being null which tells me the lambda expression is not executing appropriately, it remains null at the end of the method which tells me the highlighted line is not even being executed at all.
Example 1:
/// <summary>
/// Retrieves and stores information required for P(win) report, and then tries to send a web service request.
/// </summary>
/// <param name="service"></param>
private void LoadPwin(ReportServiceClient service)
{
string filter = string.Format("?$filter=sfa_Project/Id eq guid'{0}'", GetProjectId());
string url = GetEntitySetAddress("sfa_pwin_competitor") + filter;
WebClient client = new WebClient();
client.DownloadStringCompleted += (sender, args) =>
{
if (args.Error == null)
{
StringReader stream = new StringReader(args.Result);
XmlReader reader = XmlReader.Create(stream);
List<PWin> pwins = new List<PWin>();
List<Dictionary<string, string>> dictionaries = LoadEntitiesFromXml(reader);
foreach (Dictionary<string, string> dictionary in dictionaries)
{
PWin pwin = new PWin();
pwin.CompanyName = ParseDictionaryValue(dictionary["sfa_competitor"]);
pwin.IsBoeing = (ParseDictionaryValue(dictionary["sfa_is_boeing"]) == "true");
pwin.IsDomestic = (ParseDictionaryValue(dictionary["sfa_domestic_or_international"]) == "true");
pwin.AffordabilityWeight = ParseDictionaryValueToNumber(dictionary["sfa_affordability_weight"]);
pwin.AffordabilityScore = ParseDictionaryValueToNumber(dictionary["sfa_affordability_score"]);
pwin.CustomerRelationshipWeight = ParseDictionaryValueToNumber(dictionary["sfa_customer_relationship_weight"]);
pwin.CustomerRelationshipScore = ParseDictionaryValueToNumber(dictionary["sfa_customer_relationship_score"]);
pwin.CustomerAdvantageWeight = ParseDictionaryValueToNumber(dictionary["sfa_customer_advantage_weight"]);
pwin.CustomerAdvantageScore = ParseDictionaryValueToNumber(dictionary["sfa_customer_advantage_score"]);
pwin.CompetitionWeight = ParseDictionaryValueToNumber(dictionary["sfa_competition_weight"]);
pwin.CompetitionScore = ParseDictionaryValueToNumber(dictionary["sfa_competition_score"]);
pwin.CPOBCWeight = ParseDictionaryValueToNumber(dictionary["sfa_cpobc_weight"]);
pwin.CPOBCScore = ParseDictionaryValueToNumber(dictionary["sfa_cpobc_score"]);
pwin.CompanyResourcesWeight = ParseDictionaryValueToNumber(dictionary["sfa_company_resources_weight"]);
pwin.CompanyResourcesScore = ParseDictionaryValueToNumber(dictionary["sfa_company_resources_score"]);
pwin.CompanyResourcesInvestmentWeight = ParseDictionaryValueToNumber(dictionary["sfa_company_resources_investment_weight"]);
pwin.CompanyResourcesInvestmentScore = ParseDictionaryValueToNumber(dictionary["sfa_company_resources_investment_score"]);
pwin.ProgramBackgroundWeight = ParseDictionaryValueToNumber(dictionary["sfa_program_background_weight"]);
pwin.ProgramBackgroundScore = ParseDictionaryValueToNumber(dictionary["sfa_program_background_score"]);
pwin.ContinuityOfEffortWeight = ParseDictionaryValueToNumber(dictionary["sfa_continuity_of_effort_weight"]);
pwin.ContinuityOfEffortScore = ParseDictionaryValueToNumber(dictionary["sfa_continuity_of_effort_score"]);
pwin.ExecutionWeight = ParseDictionaryValueToNumber(dictionary["sfa_execution_weight"]);
pwin.ExecutionScore = ParseDictionaryValueToNumber(dictionary["sfa_execution_score"]);
pwin.TechnicalSolutionWeight = ParseDictionaryValueToNumber(dictionary["sfa_technical_solution_weight"]);
pwin.TechnicalSolutionScore = ParseDictionaryValueToNumber(dictionary["sfa_technical_solution_score"]);
pwin.StrategyToWinWeight = ParseDictionaryValueToNumber(dictionary["sfa_strategy_to_win_weight"]);
pwin.StrategyToWinScore = ParseDictionaryValueToNumber(dictionary["sfa_strategy_to_win_score"]);
pwin.ManagementStrengthWeight = ParseDictionaryValueToNumber(dictionary["sfa_management_strength_weight"]);
pwin.ManagementStrengthScore = ParseDictionaryValueToNumber(dictionary["sfa_management_strength_score"]);
pwin.CustomerPercievedCommitmentWeight = ParseDictionaryValueToNumber(dictionary["sfa_customers_percieved_commitment_weight"]);
pwin.CustomerPercievedCommitmentScore = ParseDictionaryValueToNumber(dictionary["sfa_customers_percieved_commitment_score"]);
pwin.PastPerformanceWeight = ParseDictionaryValueToNumber(dictionary["sfa_past_performance_weight"]);
pwin.PastPerformanceScore = ParseDictionaryValueToNumber(dictionary["sfa_past_performance_score"]);
pwin.RawPWin = ParseDictionaryValueToDecimal(dictionary["sfa_pwin_score"]);
pwin.RelativePWin = ParseDictionaryValueToDecimal(dictionary["sfa_relative_pwin_score"]);
pwins.Add(pwin);
}
project.PWins = new ObservableCollection<PWin>(pwins);
PwinReady = true;
reader.Close();
TrySendRequest(service);
}
};
client.DownloadStringAsync(new Uri(url));
}
Example 2 the project.TeamMembers value below ends up being null:
/// <summary>
/// Retrieves and stores information required for Capture Team Roster report, and then tries to send a web service request.
/// </summary>
/// <param name="service"></param>
private void LoadCaptureTeamRoster(ReportServiceClient service)
{
string filter = string.Format("?$select=sfa_name,sfa_Role&$filter=sfa_Project/Id eq guid'{0}'", GetProjectId());
string url = GetEntitySetAddress("sfa_team_roster") + filter;
WebClient client = new WebClient();
client.DownloadStringCompleted += (sender, args) =>
{
if (args.Error == null)
{
StringReader stream = new StringReader(args.Result);
XmlReader reader = XmlReader.Create(stream);
List<TeamMember> members = new List<TeamMember>();
List<Dictionary<string, string>> dictionaries = LoadEntitiesFromXml(reader);
foreach (Dictionary<string, string> dictionary in dictionaries)
{
TeamMember member = new TeamMember();
member.Name = ParseDictionaryValue(dictionary["sfa_name"]);
member.Role = ParseDictionaryValue(dictionary["sfa_role"]);
members.Add(member);
}
project.TeamMembers = new ObservableCollection<TeamMember>(members);
CaptureTeamRosterReady = true;
reader.Close();
TrySendRequest(service);
}
};
client.DownloadStringAsync(new Uri(url));
}
Here is another example that is not an issue with a relational, but instead is an issue with a field populated on a project entity in CRM that shows up empty after retrieving the data. Both CaptureTeamLeader and ProgramManager end up being empty strings, however the ProjectName and ProjectNumber have no troubles populating
private void LoadCampaignTitle(ReportServiceClient service)
{
project.ProjectName = GetAttributeValue("sfa_name");
project.ProjectNumber = GetAttributeValue("sfa_project_number");
project.CaptureTeamLeader = GetAttributeValue("sfa_capture_team_leader_emp");
project.ProgramManager = GetAttributeValue("sfa_program_manager_emp");
CampaignTitleReady = true;
TrySendRequest(service);
}
Any help would be greatly appreciated. Thanks in advance!
EDIT:
This is the AttributeValue method asked for:
/// <summary>
/// Gets the value of provided attribute from the current page's Xrm data. If for any reason the retrieval fails, returns an empty string.
/// </summary>
/// <param name="attributeName"></param>
/// <returns></returns>
private string GetAttributeValue(string attributeName)
{
// NOTE: This is the preferred way to retrieve data from the CRM. However for some unknown issue,
// this always returns NULL. It will be replaced with directly calling .eval to the window object.
// dynamic Xrm = (ScriptObject)HtmlPage.Window.GetProperty("window.parent.Xrm");
try
{
return HtmlPage.Window.Invoke("getAttributeValue", attributeName).ToString();
}
catch (ArgumentNullException)
{
return string.Empty;
}
catch (ArgumentException)
{
return string.Empty;
}
catch (InvalidOperationException)
{
return string.Empty;
}
}
The solution to this problem was that number 1 The downloadstringasync and other places in my code were doing things asynchronously and therefore the debugger was throwing me off and showing things as null when they were really just being executed later. The actual fix required some changes to a client.xml file in the folder the webservice was being hosted from.

Cannot find com.apiconnector.API in the dotMailer API for C#

I am trying to make sense of the dotMailer API for C#.
I have a class library where I intend to store the functionality that will consume the dotMailer API which references version 1.5 of the API. I also have a Service Reference set up from this WSDL
I was looking through the C# examples, but already I'm stumped! The following was pulled directly from here
Example of use in C#
/// <summary>
/// Adds a contact to an address book
/// </summary>
public void AddContactToAddressBook()
{
const string username = "apiuser-XXXXXXXXXXXX#apiconnector.com";
const string password = "password";
const int addressBookId = 1; // ID of the target address book
Console.WriteLine("AddContactToAddressBook");
Console.WriteLine("-----------------------");
// Get an instance to the web reference
com.apiconnector.API api = new com.apiconnector.API();
try
{
// we need a new contact
com.apiconnector.APIContact contact = new com.apiconnector.APIContact();
// populate the contact
contact.AudienceType = com.apiconnector.ContactAudienceTypes.B2B;
// populate the data fields
contact.DataFields = new com.apiconnector.ContactDataFields();
contact.DataFields.Keys = new string[3];
contact.DataFields.Values = new object[3];
contact.DataFields.Keys[0] = "FIRSTNAME";
contact.DataFields.Values[0] = "John";
contact.DataFields.Keys[1] = "LASTNAME";
contact.DataFields.Values[1] = "Smith";
contact.DataFields.Keys[2] = "POSTCODE";
contact.DataFields.Values[2] = "IP4 1XU";
// email address
contact.Email = "joe.smith#example.com";
contact.EmailType = com.apiconnector.ContactEmailTypes.PlainText;
contact.Notes = "This is a test only email";
contact.OptInType = com.apiconnector.ContactOptInTypes.Single;
// This method will create the contact required if it doesn't already exist within the dotMailer system,
// so we don't have to call CreateContact as a prerequisite.
//
// This method will also overwrite an existing contact, with the information provided here.
//
// This method will fail if you try to add a contact to the "Test" or "All Contacts" address books.
//
com.apiconnector.APIContact newContact = api.AddContactToAddressBook(username, password, contact, addressBookId);
// Did we get something back from the API ?
if (newContact != null)
{
Console.WriteLine("Contact added to address book {0} -> {1}", newContact.ID, addressBookId);
}
}
catch (SoapException ex) // catch any soap issues/errors from the web service
{
Console.WriteLine("Error -> {0}", ex.Message);
}
Console.WriteLine();
}
My problem is that the following line does not resolve.
com.apiconnector.API api = new com.apiconnector.API();
I have looked in namespace dotMailer.Sdk.com.apiconnector for API but it does not exist, so where is it?
Am I missing something?
Add the wsdl as a service reference. In the example below I've called it "ServiceReference1" (because that's the default and I was lazy). You then use the reference to the APISoapClient (I've called it Client) instead of "api" that you're having trouble declaring.
All compiles fine, I'm not going to execute it because I've no idea what shenanigans my random code snippet is going to cause for the server! Should point you in the right direction?
using WindowsFormsApplication1.ServiceReference1;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
const string username = "apiuser-XXXXXXXXXXXX#apiconnector.com";
const string password = "password";
const int addressBookId = 1; // ID of the target address book
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
AddContactToAddressBook();
}
private void AddContactToAddressBook()
{
using (ServiceReference1.APISoapClient Client = new ServiceReference1.APISoapClient())
{
APIContact Contact = new APIContact();
Contact.AudienceType = ContactAudienceTypes.B2B;
APIContact NewContact = Client.AddContactToAddressBook(username, password, Contact, addressBookId); // etc. etc.
}
}
}
}

Categories