WCF service taking userPincipleNname instead of passed in string as argument - wcf

This is a weird issue. I am passing in strings into my service, and that string would be the username of the person logged into my website (via windows authorization). I get the string from my website using
HttpContext.User.Identity.Name.ToString()
I parse it from the domain and just get the user Identity. And then I call a wcf service whose contract is similar to this...
generalWCFContractImplementation(string userID);
Now, you would think it would pass in the string that I sent it... However, that is indeed not the case. After doing some debugging, I found out that the string that is being passed in is the userPrincipleName that I am using to setup the WCF connection! Now why on earth would it do that? I am checking all throughout my code to see if accidentally change the userID in some way, but I check as soon as I enter the function what the value of the ID is, and it is the userPrincipleName! I am extremely confused about what is going on here. Does anybody have any idea why that would occur? and how can I remedy that?
Thanks.
UPDATED with code
public string GetOwnedPopulations(string userID)
{
Log.TraceEvent(System.Diagnostics.TraceEventType.Information, string.Format("Entered Method GetOwnedPopulations() CallerNameOnly: {0}, userID: {1} CallerNameOnly==userID {2}", CallerNameOnly, userID, CallerNameOnly == userID), "General");
this.CallerFullDomain = userID;
this.CallerNameOnly = userID;// this.CallerFullDomain.Substring(this.CallerFullDomain.IndexOf('\\') + 1);
string ans;
Log.TraceEvent(System.Diagnostics.TraceEventType.Information, string.Format("Entered Method GetOwnedPopulations() CallerNameOnly: {0}, userID: {1} CallerNameOnly==userID {2}", CallerNameOnly , userID, CallerNameOnly==userID), "General");
searchPopulationbyOwner oReq = new searchPopulationbyOwner();
oReq.ownerName = this.CallerNameOnly;
try
{
StringBuilder sbBuffer = new StringBuilder();
PopulationManagementClient client = UPMC.ISD.EADIS.PopulationManagement.PopManSvc.Utils.GetClient(this.CallerNameOnly);
searchPopulationbyOwnerResponse resp = client.searchPopulationbyOwner(oReq);
Log.TraceEvent(System.Diagnostics.TraceEventType.Information, string.Format("Getting Null Values?: {0}", (resp == null ? ans="yes" : ans="no")), "General");
XmlSerializer xs = new XmlSerializer(typeof(Population[]));
System.IO.StringWriter sw = new System.IO.StringWriter(sbBuffer);
xs.Serialize(sw, resp.populationList);
string sPopulationtXML = sbBuffer.ToString();
return sPopulationtXML;// client.searchPopulationbyOwner(oReq);
}
catch
{
throw;
}
}
As you can see, I pass in the username, and I then set the object that I am going to pass in equal to the user ID. The thing is, userID is either the applicationPoolID, but I am guessing more than likely it is the userPrincipleName (which would happen to be the same as the applicationPoolIdentity... I am not sure if they have to be the same or not). But this is very weird. I have know idea why on earth that would be passed in and not the actual username... And yes, I have looked at my site to see what is being passed in, and it is indeed, the userID... When it hits the service however, it is the userPrincipleName.
Confused?????

Related

Marketo rest Api create lead

I have a question about this create/Update leads API, http://developers.marketo.com/documentation/rest/createupdate-leads/.
There is no sample code for C# or JAVA. Only ruby available. So I have to try it by myself. But I always get null return from the response.
Here is my code:
private async Task<CreateLeadResponseResult> CreateLead(string token)
{
string url = String.Format(marketoInstanceAddress+"/rest/v1/leads.json?access_token={0}", token);
var fullUri = new Uri(url, UriKind.Absolute);
CreateLeadResponseResult createLeadResponse = new CreateLeadResponseResult();
CreateLeadInput input = new CreateLeadInput { email = "123#123.com", lastName = "Lee", firstName = "testtesttest", postCode = "00000" };
CreateLeadInput input2 = new CreateLeadInput { email = "321#gagaga.com", lastName = "Lio", firstName = "ttttttt", postCode = "00000" };
List<CreateLeadInput> inputList = new List<CreateLeadInput>();
inputList.Add(input);
inputList.Add(input2);
CreateLeadRequest createLeadRequest = new CreateLeadRequest() { input = inputList };
JavaScriptSerializer createJsonString = new JavaScriptSerializer();
string inputJsonString = createJsonString.Serialize(createLeadRequest);
using (var client = new HttpClient())
{
HttpResponseMessage response = await client.PostAsJsonAsync(fullUri.OriginalString, inputJsonString).ConfigureAwait(false);
// I can see the JSON string is in the message body in debugging mode.
if (response.IsSuccessStatusCode)
{
createLeadResponse = await response.Content.ReadAsAsync<CreateLeadResponseResult>();
}
else
{
if (response.StatusCode == HttpStatusCode.Forbidden)
throw new AuthenticationException("Invalid username/password combination.");
else
throw new ApplicationException("Not able to get token");
}
}
return createLeadResponse;}
//get null here.
Thank you.
-C.
The best way to debug this is to capture the exact URL, parameters and JSON that are submitted by your app and try submitting those manually via a tool like Postman (Chrome plug-in) or SOAP UI. Then you see the exact error message, which you can look up here: http://developers.marketo.com/documentation/rest/error-codes/. Based on that you can update your code. I don't know much about Java, but this is how I got my Python code to work.
Your example code was really helpful in getting my own implementation off the ground. Thanks!
After playing with it for a bit, I realized that the JavaScriptSerializer step is unnecessary since PostAsJsonAsync automatically serializes whatever object you pass to it. The double serialization prevents Marketo's API from processing the input.
Also, I agree with Jep that Postman is super helpful. But in the case of this error, Postman was working fine (using the contents of inputJsonString) but my C# code still didn't work properly. So I temporarily modified the code to return a dynamic object instead of a CreateLeadResponseResult. In debugging mode this allowed me to see fields that were discarded because they didn't fit the CreateLeadResponseResult type, which led me to the solution above.

What uri pattern do I need to communicate with my PC from my handheld device?

As I was reminded here, I need to probably use "ppp_peer" to programmatically connect from my Compact Framework app to my Web API app running on my PC.
I have tried this (replacing an IPAddress with "ppp_peer"):
string uri = string.Format("http://ppp_peer:28642/api/FileTransfer/GetHHSetupUpdate?serialNum={0}&clientVersion={1}", serNum, clientVer);
...but I get, "NullReferenceException" in "Main" (prior to this I got "Unable to Connect to the Remote Server").
I have a breakpoint in the server code, but it doesn't reach that, so it must be somewhere in the client where this is occurring.
The client code in context is:
string uri = string.Format("http://ppp_peer:28642/api/FileTransfer/GetHHSetupUpdate?serialNum={0}&clientVersion={1}", serNum, clientVer);
RESTfulMethods.DownloadNewerVersionOfHHSetup(uri);
. . .
public static void DownloadNewerVersionOfHHSetup(string uri)
{
string dateElements = DateTime.Now.ToString("yyyyMMddHHmmssfff", CultureInfo.InvariantCulture);
var outputFileName = string.Format("HHSetup_{0}.exe", dateElements);
try
{
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
var webResponse = (HttpWebResponse)webRequest.GetResponse();
string statusCode = webResponse.StatusCode.ToString();
if (statusCode == "NoContent")
{
MessageBox.Show("You already have the newest available version.");
}
else
{
var responseStream = webResponse.GetResponseStream();
using (Stream file = File.Create(outputFileName))
{
CopyStream(responseStream, file);
MessageBox.Show(string.Format("New version downloaded to {0}", outputFileName));
}
}
}
catch (WebException webex)
{
string msg = webex.Message;
string innerEx = webex.InnerException.ToString();
string status = webex.Status.ToString();
MessageBox.Show(string.Format("Message: {0}; Status: {1}; inner Ex: {2}", msg, status, innerEx));
}
}
Do I need an IPAddress in addition to ppp_peer, or is my formatting of the URI wrong, or...???
UPDATE
After the "NRE" I also see, ""...encountered a serious error and must shut down"
I changed the code from above to see just what ppp_peer is translated as:
IPAddress ipAd = Dns.Resolve("PPP_PEER").AddressList[0];
string IPAddr = ipAd.ToString();
MessageBox.Show(IPAddr);
string uri = string.Format("http://{0}:28642/api/FileTransfer/GetHHSetupUpdate?serialNum={1}&clientVersion={2}", IPAddr, serNum, clientVer);
The MessageBox call shows me "192.168.55.100" which is different from what I thought my PC's IPAddress was...???
I get the same with:
IPAddress ipAd = Dns.GetHostEntry("PPP_PEER").AddressList[0];
UPDATE 2
Using this instead (I got it from here [Get ip address of host pc from windows mobile when connected via ActiveSync):
IPAddress ipAd = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0];
...the IP Address displayed is "one up" (192.168.55.101), and instead of an NRE, I get:
Message: Unable to connect to the remote server; Status: ConnectFailure; inner Ex: System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it at System.Net.Sockets.SocketConnectNoCheck(EndPoint remoteEP) ...
So it seems I'm doing all I can on the client end, and the server hears the knock, but is not opening the door - am I right?
BTW, out of curiosity I also added this code:
string hostName = Dns.GetHostName();
MessageBox.Show(string.Format("host name is {0}", hostName));
...and I see "WindowsCE"
UPDATE 3
According to this post by Andy Wiggly (the cat/bloke who wrote "MS .NET Compact Framework"), you do use "ppp_peer":
HttpWebRequest request = REST.CreateRequest(#"http://ppp_peer/DataServicesWebsite/NorthwindService.svc/Customers",
HttpMethods.GET, String.Empty, #"application/atom+xml", "", "");
The interestingest thing about this is the lack of a port assignment (":28642" or whatever); however, this style also gives me an NRE (yes, kind of like a Null Ready to Eat).
UPDATE 4
So what uri will it take to access the host machine from the handheld device?
I have tried all of the following permutations from the client/Compact Framework app, and none work:
IPAddress ipAd = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0];
string IPAddr = ipAd.ToString();
//string uri = string.Format("http://ppp_peer/api/...
//string uri = string.Format("http://ppp_peer:28642/api...
//string uri = string.Format("http://PPP_PEER/api/...
string uri = string.Format("http://PPP_PEER:28642/api/...
//string uri = string.Format("http://{0}:28642/api/...
//string uri = string.Format("http://192.168.125.50:28642/api/...
//string uri = string.Format("http://Platypus:28642/api/...
RESTfulMethods.DownloadNewerVersionOfHHSetup(uri);
The error is happening somewhere in that client code (can't step through it, so I don't know exactly where), because I have a breakpoint on the last line shown, and it is never reached.
SERVER (Web API) code:
[Route("api/FileTransfer/GetUpdatedHHSetup")]
public HttpResponseMessage GetUpdate(string serialNum, string clientVersion)
{
return _fileTransfer.GetHHSetupUpdate(serialNum, clientVersion);
}
public HttpResponseMessage GetHHSetupUpdate(string serialNum, string clientVersion)
{
HttpResponseMessage result;
string filePath = GetAvailableUpdateForCustomer(serialNum); // <= breakpoint on this
line
I put some debug lines in DownloadNewerVersionOfHHSetup() so that it now looks like this:
public static void DownloadNewerVersionOfHHSetup(string uri)
{
MessageBox.Show("Made it into DownloadNewerVersionOfHHSetup");
string dateElements = DateTime.Now.ToString("yyyyMMddHHmmssfff",
CultureInfo.InvariantCulture);
var outputFileName = string.Format("HHSetup_{0}.exe", dateElements);
try
{
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
MessageBox.Show("Made it into DownloadNewerVersionOfHHSetup #2");
var webResponse = (HttpWebResponse)webRequest.GetResponse();
MessageBox.Show("Made it into DownloadNewerVersionOfHHSetup #3");
. . .
I never see "#3", so it must be a problem inside the call to GetResponse(), but how can I find out exactly what? I get the NRE, then "...encountered a serious error and must shut down"
This is where it tries to call the server but, as mentioned, it never makes it to the server method being called...
UPDATE 5
It turns out that this now works:
http://192.168.125.50:28642/api/
...and the main reason that it does is because there was a mismatch between my routing attribute (GetUpdatedHHSetup) and what I was calling from the client (GetHHSetupUpdate). Once I aligned those planets, the NRE went away, and I got the expected result.
PPP_PEER is not needed in the uri/connection string. Using the host PC's IP Address (and port number for the server/Web API app) works now (after fixing the mismatch between the routing attribute and what the client was calling it).
I reckon using the machine name would work just as well, too.

What is the purpose of the out queue in RedisMQ?

In the Re-usability use-case project with RedisMQ there is a SMessageService which has the following handler.
SMessageService :Service{
public object Any(EmailMessage request)
{
var sw = Stopwatch.StartNew();
Db.InsertAll(Email.Process(request));
return new SMessageResponse { TimeTakenMs = sw.ElapsedMilliseconds };
}...
}
When the services returns, it puts the message in the mq:SMessageResponse.inq list.
My questions is if I return null instead of new SMessageResponse{...}, a message is put in the mq:EmailMessage.outq list, what is the reason for this?
Also, if I don't want to return a response at all, how would I do this or is this bad practice in the area of messaging?. In other words, I always need to have a log of what has happened.

How to manipulate LDAP using JNDI on websphere?

I am facing a problem with an LDAP operation. I want to dynamically add a member to an LDAP group when selected by the user from GUI / browser. I paste the code below which works perfectly well when I run it in a Test class (using com.sun.jndi.ldap.LdapCtxFactory). But, when I package it in my build, deploy on websphere app server 7.0 (using com.ibm.websphere.naming.WsnInitialContextFactory), and invoke this method according to user's selection, then I get the error below. I wonder what's wrong I am doing. Doesn't WAS provide implementation of ldap connection factory? I also tried deploying on WAS with the sun's ldap which otherwise works on the Test class, but I am getting the same exception as below. I'd appreciate if anybody can give a clue.
Problem adding member: javax.naming.OperationNotSupportedException: [LDAP: error code 53 - 00000561: SvcErr: DSID-031A120C, problem 5003 (WILL_NOT_PERFORM), data 0
My Code:
public class LDAPManager
{
String GROUPS_OU = "cn=users,dc=mit,dc=hq,dc=com";
public Boolean addMember(String user, String group)
{
Hashtable env = new Hashtable();
String adminName = "CN=Administrator,CN=Users,DC=mit,DC=hq,DC=com";
String adminPassword = "asdfasdf21Q";
String ldapURL = "ldap://mybox451Dev.mit.hq.com:389";
String userName = "CN="+user+",CN=Users,DC=mit,DC=hq,DC=com";
String groupName = "CN="+group+",CN=Users,DC=mit,DC=hq,DC=com";
//env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.ibm.websphere.naming.WsnInitialContextFactory");
//set security credentials, note using simple cleartext authentication
env.put(Context.SECURITY_AUTHENTICATION,"simple");
env.put(Context.SECURITY_PRINCIPAL,adminName);
env.put(Context.SECURITY_CREDENTIALS,adminPassword);
//connect to my domain controller
env.put(Context.PROVIDER_URL, "ldap://mybox451Dev.mit.hq.com:389");
try {
// Create the initial directory context
InitialDirContext ctx = new InitialDirContext(env);
//Create a LDAP add attribute for the member attribute
ModificationItem mods[] = new ModificationItem[1];
mods[0]= new ModificationItem(DirContext.ADD_ATTRIBUTE, new BasicAttribute("member", userName));
//update the group
ctx.modifyAttributes(groupName,mods);
ctx.close();
//System.out.println("Added " + userName + " to " + groupName);
}
catch (NamingException e) {
System.err.println("Problem adding member: " + e);
}
return true;
}
}
I got it solved. Posting solution here, hope this helps someone.
Use the standard JNDI context of sun, not websphere.
Additional properties I was missing in the hashtable, once I added them, it worked like a charm.
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
//env.put(Context.INITIAL_CONTEXT_FACTORY,"com.ibm.websphere.naming.WsnInitialContextFactory");
//set security credentials, note using simple cleartext authentication
env.put(Context.SECURITY_AUTHENTICATION,"simple");
env.put(Context.SECURITY_PRINCIPAL,adminName);
env.put(Context.SECURITY_CREDENTIALS,adminPassword);
env.put(Context.URL_PKG_PREFIXES, "com.sun.jndi.url");
env.put(Context.REFERRAL, "ignore");
Well, it's been more than a year since this question has been asked; so, I don't know answering will add any value. But, here it is. See WAS Javadocs for details on how what that factory class actually does and how it works. You may need to adjust your jndiprovider.properties file for WAS.

Creating an SPListItem in a WCF service deployed to SharePoint

i have the following method in a WCF service, that has been deployed to SharePoint using Shail Malik's guide:
[OperationContract]
public string AddItem(string itemTitle, Guid? idOfListToUse)
{
using (var portal = new SPSite(SPContext.Current.Site.Url, SPContext.Current.Site.SystemAccount.UserToken))
{
using (var web = portal.OpenWeb())
{
Guid listId;
web.AllowUnsafeUpdates = true;
if (idOfListToUse != null && idOfListToUse.Value != new Guid())
{
listId = idOfListToUse.Value;
}
else
{
try
{
listId = new Guid(web.Properties[PropertyBagKeys.TagsList]);
}
catch (Exception ex)
{
throw new MyException("No List Id for the tag list (default list) has been found!", ex);
}
}
var list = web.Lists[listId];
string title = "";
SPSecurity.RunWithElevatedPrivileges(delegate{
var newItem = list.Items.Add();
newItem["Title"] = itemTitle;
newItem.Update();
title = newItem.Title;
});
web.AllowUnsafeUpdates = false;
return title;
}
}
}
When the method gets called from Javascript (using Rick Strahl's excellent ServiceProxy.js) it fails and it does so on newItem.Update() because of ValidateFormDigest().
Here's the kicker though, when I step through the code it works! No exceptions at all!
Ok, found the answer (there's 2 even :-D)
First, the dirty one:
Set FormDigestValidatedProperty in the context:
HttpContext.Current.Items["FormDigestValidated"] = true;
Second, the slightly less dirty version (basically leaving the way open for XSS attacks, but this is an intranet anyway)
The answer
I don't think you can access 'list' as it was created outside the elevated code block.
http://blogs.pointbridge.com/Blogs/herzog_daniel/Pages/Post.aspx?_ID=8
I'm guessing when you are stepping though the entire process is in admin mode so all are elevated.
Colin, it's a really bad idea to try to access HttpContext (likewise SPContext) inside a WCF service. See here: MSDN: WCF Services and ASP.NET
From the article:
HttpContext: Current is always null
when accessed from within a WCF
service.
It's likely this is the cause of your problem.
EDIT: I notice that you're trying to use SPContext to get the url of the site collection. I didn't find a good solution to this either so I just send the url of the target site collection as a parameter to the service call. Not the most optimal solution but I couldn't think of a better way. Also, if you need to check authentication/identities, etc use ServiceSecurityContext.Current.