Call a web service method dynamically from client app - c#

I am testing a client application with a web reference to a web service; the web reference is called "PrinterStatus".
In this application I populate a dropdown list with list of available method names. I want to call the method user has selected and not sure how to set it up.
private void PopulateDropdown()
{
// web service URL
string url = "http://1.2.3.4/PS_WS/PrinterStatus.asmx?WSDL";
WebServiceInfo webServiceInfo = WebServiceInfo.OpenWsdl(new Uri(url));
foreach (WebMethodInfo method in webServiceInfo.WebMethods)
{
ListItem li = new ListItem(method.Name);
ddlMethods.Items.Add(li);
}
}
This populates the drop down list with list of available methods (the code for "WebServiceInfo" is at this link).
When user clicks "Submit", I want to be able to call:
PrinterStatus ps = new PrinterStatus();
string sResp = ps.<method_name_user_selected>();
Update
Following Xerillio's recommendation, I made the following changes to get this to work. In my test client app I have a dropdown populated with available method names (ddlMethods) and two textboxes for IP address and port number of printer whose status I am interested in (tbIP and tbPort) and a "submit" button. I have removed all validation stuff.
Also, the web reference created in client app is named "PrinterStatus". The methods in web service return a JSON object.
protected void btnSubmit_Click(object sender, EventArgs e)
{
string sMethodName = ddlMethods.SelectedValue;
string sIPAddress = tbIP.Text.Trim();
string sPort = tbPort.Text.Trim();
int iPort = int.Parse(sPort);
PrinterStatus ps = new PrinterStatus();
Type thisType = ps.GetType();
MethodInfo theMethod = thisType.GetMethod(sMethodName);
string sResp = theMethod.Invoke(ps, new object[] {sIPAddress, iPort}) as string;
Response resp = JsonConvert.DeserializeObject<Response>(sResp);

Related

how to change selected value in html using c#?

im trying to get some datas from a webpage. im writing code in c# .net. the webpage has a dropdown list (or combobox) like i showed below. data changes according to selected dropdown list item but url does not change. my question is how can my code changes selected values and get datas from webpage? i parsed and got for only one of items like that:
**WebClient wc = new WebClient();
string kaynak = wc.DownloadString("http://www.diyanet.gov.tr/");
string imsak = "spImsak";
int imindex = kaynak.IndexOf(imsak);
imindex += 9;
System.Console.WriteLine(kaynak.Substring(imindex, 5));**
< span id="spImsak">02:44< /span >
i downloaded html code of webpage as a string. searched "spImsak". finally i got "02:44" as a string. and i wanna do it for all combobox items. can you give me any advice?
sample webpage : http://www.diyanet.gov.tr/
red ones are comboboxes. yellow one is data that i wanna get.
i have followed up webpage's network and saw that when i click any dropdown list element, webpage runs a web service with parameters. i explain how to applied that to my question.
web service and parameters image
all i need send a POST request this web service with these parameters and got string (json). i did that following c# code.
using (WebClient client = new WebClient())
{
int turn;
byte[] response;
string result;
/* gets response for 81 city */
for (turn = 500; turn < 581; ++turn)
{
response =
client.UploadValues("http://diyanet.gov.tr/PrayerTime/MainPrayerTimesSet", new NameValueCollection()
{
{ "countryName", "2" },
{ "name", turn.ToString() }
});
/* without sleep, web service does not response successive requests */
System.Threading.Thread.Sleep(5);
/* turns incoming byte[] -> string */
result = System.Text.Encoding.UTF8.GetString(response);
Console.WriteLine(result);
}
}

How to return an ArrayList from a WebService in C#?

I have been trying to return an ArrayList from a WebService and I am confused about how to get it going as I get an error message saying
"Cannot implicitly convert type 'object[]' to 'System.Collections.ArrayList'".
Here is the Code for the Web Service names DDRParserService.asmx .
public ArrayList PVTLog(string reqNo, string groupNo, string filePath)
{
ArrayList logData = new ArrayList();
//Calling the Parsing Logic file
logData = ParsePVTLog_Service(reqNo, groupNo, filePath);
// I get the ArrayList in logData and return it
return logData
}
The Code where I consume the Web Service:
private void btnParse_Click(object sender, EventArgs e)
{
string strFilePath = txtOpenFile.Text;
string serialNo = txtSerialNumber.Text;
string groupNo = txtGroupNumber.Text;
ArrayList data = new ArrayList();
if (txtOpenFile.Text != "")
{
DDRParsingService.DDRParserService client = new DDRParsingService.DDRParserService();
// Call the Web Service
data = client.PVTLog(serialNo, groupNo, strFilePath);
// I get the error : Cannot implicitly convert type 'object[]' to 'System.Collections.ArrayList'
}
}
It would be great if you can help me handle this issue and access the data in the ArrayList returned by the Web Service.
Thanks in Advance!
on your service reference click configure:
Select your expected collection type:
click OK, then update the service reference:
When calling the Web Service, all I had to do was declare the returned object from the Web Service as a new ArrayList.
In the above code that I have posted, I called the Web Service like this :
private void btnParse_Click(object sender, EventArgs e)
{
string strFilePath = txtOpenFile.Text;
string serialNo = txtSerialNumber.Text;
string groupNo = txtGroupNumber.Text;
ArrayList data = new ArrayList();
if (txtOpenFile.Text != "")
{
DDRParsingService.DDRParserService client = new DDRParsingService.DDRParserService();
// Call the Web Service
data = client.PVTLog(serialNo, groupNo, strFilePath);
// I get the error : Cannot implicitly convert type 'object[]' to 'System.Collections.ArrayList'
}
}
But all I had to do was this :
data = new ArrayList(client.PVTLog(serialNo, groupNo, strFilePath));
i.e. Declare the returned object[] from the Web Service as a new ArrayList!

Sharepoint 2013 On-Premises C# CSOM Cross Site Collection List Access

I see this has sorta been asked a bunch times before, but all the examples I am running across will not work or are in JavaScript , I NEED HELP WITH C# please.
I have a farm with server site collections on it, I successfully created a provider hosted addin/App, When it trys to access lists on the Web that launched it everything is fine! I need to try to access lists on other webs in the same farm and on the same domain does anyone have an example of C# code that can do this
You can create a repository method like this:
public class SharepointRepository
{
public ListItemCollection ListTopN(string urlSite, string listName, bool ascending, string column, int rowLimit)
{
using (var context = new ClientContext(urlSite))
{
context.Credentials = CredentialCache.DefaultCredentials;
List list = context.Web.Lists.GetByTitle(listName);
string myQuery = string.Format("<View><Query><OrderBy><FieldRef Name='{0}' Ascending='{1}' /></OrderBy></Query><RowLimit>{2}</RowLimit></View>", column, ascending.ToString(), rowLimit);
CamlQuery query = new CamlQuery();
query.ViewXml = myQuery;
ListItemCollection collection = list.GetItems(query);
context.Load(list);
context.Load(collection);
context.ExecuteQuery();
return collection;
}
}
}
this approach uses the managed csom.
and if you are facing problems with ADFS, try adding after this line
context.Credentials = CredentialCache.DefaultCredentials;
this
context.ExecutingWebRequest += new EventHandler<WebRequestEventArgs>(MixedAuthRequestMethod);
and this function
void MixedAuthRequestMethod(object sender, WebRequestEventArgs e)
{
e.WebRequestExecutor.RequestHeaders.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
}
This is a basic referente:
https://msdn.microsoft.com/en-us/library/office/fp179912.aspx
You should also look at the Sharepoint App Model and the Rest OData API.
I figured this out, so I am posting it just in case someone else needs it, also please understand that I am total noob to SharePoint and this may not be the best way or even the SharePoint Accepted way of doing things.
First you need to give you app Tenant Permission (Full Control or Manage) ! - Very Important
Second I created this function that make a n SharePoint Context to a site other then the one the app is running on
public ClientContext CreateRemoteSharePointContext(string TargetWebURL, SharePointContext CurrentSharePointContext)
{
//In order for us to create a share point client context that points to
//site other then the site that this app is running we need to copy some url parameters from the current
//context. These parameters are found on the current share-point context
NameValueCollection QueryString = Request.QueryString;
//Since, The Query string is a read only collection, a use of reflection is required to update the
//values on the request object, we must use the current request object because it contains
//security and other headers/cookies that we need for the context to be created, Grab the url params that we need
//other then TargetWebUrl, that will be the url of the site we want to manipulate
Utility.AddToReadonlyQueryString(QueryString, "SPHostUrl", CurrentSharePointContext.SPHostUrl.ToString(), System.Web.HttpContext.Current.Request);
Utility.AddToReadonlyQueryString(QueryString, "SPAppWebUrl", TargetWebURL, System.Web.HttpContext.Current.Request);
Utility.AddToReadonlyQueryString(QueryString, "SPLanguage", CurrentSharePointContext.SPLanguage, System.Web.HttpContext.Current.Request);
Utility.AddToReadonlyQueryString(QueryString, "SPClientTag", CurrentSharePointContext.SPClientTag, System.Web.HttpContext.Current.Request);
Utility.AddToReadonlyQueryString(QueryString, "SPProductNumber", CurrentSharePointContext.SPProductNumber, System.Web.HttpContext.Current.Request);
//This is a special line, we need to get the AppOnly access token and pass it along to the target site, its is a little counter intuitive
//Because we are using TokenHelper.GetS2SAccessToeknWithWindowsIdentity - but we pass NULL as the User identity, this will
//check the app manifest and if the app has a CERT and AppOnly Permission it will return a valid app only token to use
Utility.AddToReadonlyQueryString(QueryString, "AppContextToken", TokenHelper.GetS2SAccessTokenWithWindowsIdentity(new Uri(TargetWebURL), null), System.Web.HttpContext.Current.Request);
//Return the newly created context
return SharePointContextProvider.Current.CreateSharePointContext(HttpContext.Request, TargetWebURL).CreateAppOnlyClientContextForSPAppWeb();
}
As you can see the I had to kinda hack up the Querystring and grab some values so here is the Utility class that does that :
public class Utility
{
public static void UpdateReadonlyQueryString(NameValueCollection collectionToUpdate, string paramName, string paramValue, HttpRequest Request)
{
collectionToUpdate = (NameValueCollection)Request.GetType().GetField("_queryString", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(Request);
PropertyInfo readOnlyInfo = collectionToUpdate.GetType().GetProperty("IsReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
readOnlyInfo.SetValue(collectionToUpdate, false, null);
collectionToUpdate[paramName] = paramValue;
readOnlyInfo.SetValue(collectionToUpdate, true, null);
}
public static void AddToReadonlyQueryString(NameValueCollection collectionToUpdate, string paramName, string paramValue, HttpRequest Request)
{
collectionToUpdate = Request.QueryString;
collectionToUpdate = (NameValueCollection)Request.GetType().GetField("_queryString", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(Request);
PropertyInfo readOnlyInfo = collectionToUpdate.GetType().GetProperty("IsReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
readOnlyInfo.SetValue(collectionToUpdate, false, null);
collectionToUpdate.Add( paramName, paramValue);
readOnlyInfo.SetValue(collectionToUpdate, true, null);
}
}
and Finally the SharePoint access code the looks like much of the same SharePoint code out there on the web, I had to remove some stuff from it that would identify the project or who its for, but it should be easy to pick out what you need from in side
try
{
//Get the name of the sharepoint list that needs to be updated from settings
var ListName = ConfigurationManager.AppSettings[Constants.SettingsConstants.SPLaunchQueList];
var TargetSiteToUpdate = "URL TO THE SITE YOUR TRYING TO UPDATE";
//Get the sharepoint context from session
var spContext = <SOME HOW CREATE YOUR CONTEXT>
//Lets create a client context from the current sharepoint context to the target site
//NOTE this requires the application to HAVE Tenant level permission, it must be trusted by
//the farm admin
using (var spClientContext = CreateRemoteSharePointContext(TargetSiteToUpdate, spContext))
{
//Get the current Web (Sharepoint Web) from the client context
var web = spClientContext.Web;
//Load all the webs properties including title , url all the lists and get the subwebs if any as well
spClientContext.Load(web, x => x.Title, x => x.Url, x => x.Lists, x => x.Webs.Include(w => w.Title, w => w.Url));
spClientContext.ExecuteQuery();
//Lets grab the list that needs to be updated
SP.List OrgList = web.Lists.GetByTitle(ListName);
//Construct a caml query Where the groupID of the SQL Server record is the same
//as the list GroupID
var caml = new Caml<DetailParts>().Where(o => o.GroupID == updateRecord.GroupID);
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = caml.ToString();
//Load the CAML query
ListItemCollection Rows = OrgList.GetItems(camlQuery);
spClientContext.Load(Rows);
spClientContext.ExecuteQuery();
//The CAML Query should only return one row because GroupID should be UNQIUE
//however due to how sharepoint returns list data we are forcing the first value
//here
ListItem RowToUpdate = Rows[0];
//Get a list of sharepoint columns that match the local detail parts
var ColumnsToUpdate = GetSharePointColumns(typeof(DetailParts));
RowToUpDate["SomeColumn"] = "YOUR NEW VALUE";
RowToUpdate.Update();
//Commit the changes
spClientContext.ExecuteQuery();
}
}
}
catch (Exception ex)
{
//Log any exception and then throw to the caller
logger.Error("Sharepoint exception", ex);
}
That last section of code should be in a function or method of some sort I just pull out the relevant parts. As I Stated this is the only way I found that works and if someone has a better way please share it as I am not a SharePoint expert.

calling methods from an ASMX web service -error-

I am trying to write an application (simple form) that will consume(invoke) the web service (Service1.asmx) and display the results. Now, the web service has a method. Here is the code:
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public Customer getCustomer(String id)
{
Customer customer = new Customer();
customer.CustomerId = id;
customer.CustomerName = "ABC Warehouse";
customer.CustomerAddress = "123 Anywhere";
customer.CustomerCity = "Pittsburgh";
customer.CustomerState = "PA";
customer.CustomerZip = 10379;
customer.CustomerContact = "Dan Smith";
customer.CustomerPhone = "2484567890";
customer.CustomerCredit = "True";
return customer;
}
}
When I run the web service from its original project I am able to type text in the text box Example and click invoke to view the xml resultsExample. Now, the simple form I have in another project has a textbox (txt1), button (btn1), and label (lbl1). I successfully add the web service and all the functions and classes transfer. Now, what I want to happen is when you type something in the text box, click submit, and view the xml results in the label which will include the typed text from the text box, exactly like if I would of run the service on its own. Here is the code where I am having trouble:
public partial class _Default : System.Web.UI.Page
{
protected void btn1_Click(object sender, EventArgs e)
{
MyService.Service1 service = new MyService.Service1();
string message = service.getCustomer(string id);
ID = txt1.Text;
lbl1.Text = message;
}
}
Where am I going wrong? I am a beginner obviously, so all help would be appreciated.
p.s.: MyService is what I named the namespace when I added the web service
your code will not compile because getCustomer return Customer object.
protected void btn1_Click(object sender, EventArgs e)
{
MyService.Service1 service = new MyService.Service1();
MyService.Customer customer= service.getCustomer(string id);
ID = customer.CustomerId;
// here you can generate XML based on customer object if you really need to do so
lbl1.Text = GetCustomerXML(customer);// implement method to get XML
}
private string GetCustomerXML( MyService.Customer customer)
{
XmlSerializer xsSubmit = new XmlSerializer(typeof(MyService.Customer));
StringWriter sw= new StringWriter();
XmlWriter writer = XmlWriter.Create(sw);
xsSubmit.Serialize(writer, customer);
return sw.ToString();
}
First of all in service method you need to define that response format data must be in XML format. and then in client use 'XmlNode' to get data from service.
I think this post will be usefull for you
Your error is to be thinking that you're going to get XML back. You're not. You're going to get a MyService.Customer back.
FYI, you should be using "Add Service Reference" to consume the .asmx service.

Display sharepoint people/group field list's value in people editor

i want to display value of sharepoint people/group value in people editor(web part) when the page is loaded. This is the code that i use to get the value displayed in web part
if(SPContext .Current .ListItem .ID >= 1)
using (SPSite site = new SPSite("sitename"))
{
using (SPWeb web = site.OpenWeb())
{
var id = SPContext.Current.ListItem.ID;
SPList lists = web.Lists["DDClist"];
SPListItem item = lists.GetItemById(id);
{
string test = Convert.ToString(item["Project No"]);
tb_pno.Text = test;
string test2 = Convert.ToString(item["Project Title"]);
tb_pname.Text = test2;
string test3 = Convert.ToString(item["DDC No"]);
tb_idcno.Text = test3;
string test4 = Convert.ToString(item["Date In"]);
TextBox3.Text = test4;
}
}
}
is there a way to do the same thing with people editor?
This is all a little tricky; when I've had to do it before, I use the following to get SPUser object out of a field:
SPUser singleUser = new SPFieldUserValue(
item.Web, item["Single User"] as string).User;
SPUser[] multipleUsers = ((SPFieldUserValueCollection)item["MultipleUsers"])
.Cast<SPFieldUserValue>().Select(f => f.User);
I'm not sure why one user is stored as a string, but multiple users are stored as a specific object; it may also not be consistent in this so you might have to debug a bit and see what the type in your field is.
Once you have these SPUsers, you can populate your PeopleEditor control
using the account names as follows (quite long-winded):
ArrayList entityArrayList = new ArrayList();
foreach(SPUser user in multipleUsers) // or just once for a single user
{
PickerEntity entity = new PickerEntity;
entity.Key = user.LoginName;
entity = peMyPeople.ValidateEntity(entity);
entityArrayList.Add(entity);
}
peMyPeople.UpdateEntities(entityArrayList);
This also performs validation of the users of some kind.
If the page this control appears on may be posted-back, you need the following to be done during the postback in order for the values to be correctly roundtripped; I put it in PreRender but it could happen elsewhere in the lifecycle:
protected override void OnPreRender(EventArgs e)
{
if (IsPostBack)
{
var csa = peMyPeople.CommaSeparatedAccounts;
csa = peMyPeople.CommaSeparatedAccounts;
}
}
If you want to check any error messages that the control generates for you (if the user input is incorrect), you need to have done this switchout already:
var csa = usrBankSponsor.CommaSeparatedAccounts;
csa = usrOtherBankParties.CommaSeparatedAccounts;
//ErrorMessage is incorrect if you haven't done the above
if (!String.IsNullOrEmpty(usrBankSponsor.ErrorMessage))
{
...
}
It's really not very nice and there may be a much better way of handling it, but this is the result of my experience so far so hopefully it will save you some time.

Categories