I just wrote my first web service so lets make the assumption that my web service knowlege is non existant. I want to try to call a dbClass function from the web service. However I need some params that are in the session. Is there any way I can get these call these session variables from the webservice??
If you are using ASP.NET web services and you want to have a session environment maintained for you, you need to embellish your web service method with an attribute that indicates you require a session.
[WebMethod(EnableSession = true)]
public void MyWebService()
{
Foo foo;
Session["MyObjectName"] = new Foo();
foo = Session["MyObjectName"] as Foo;
}
Once you have done this, you may access session objects similar to aspx.
Metro.
You should avoid increasing the complexity of the service layer adding session variables. As someone previously pointed out, think of the web services as isolated methods that take all what is needed to perform the task from their argument list.
In general web services should not rely on session data. Think of them as ordinary methods: parameters go in and an answer comes out.
if you have to want Session["username"].ToString(); as in the other C# pages behind aspx then you should simply replace [WebMethod] above the WebService method with [WebMethod(EnableSession = true)]
thanks to :) Metro
Maybe this will work HttpContext.Current.Session["Name]
Or else you might have to take in some parameters or store them in a Database
Your question is a little vague, but I'll try my best to answer.
I'm assuming that your session variables exist on the server that is making the webservice call, and not on the server that hosts the webservice. In that case, you will need to pass the necessary values as parameters of your web service methods.
To use session in webservice we have to follow 2 steps-
Use [WebMethod(EnableSession = true)] attribute on the method.
Session["Name"] =50 (what ever you want to save)
Please check the following Example.
[WebMethod(EnableSession = true)]
public void saveName(string pname)
{
Session["Name"] = pname;
}
Related
I've researched the web extensively before posting this questions here, couldn't find anything usefull for me, so here it goes. Sorry in advance for the wall of text.
I have a classic ASP website that needs to call a web service method (not wcf, but an asmx page) on a asp.net website (4.0)
The way I consume the web service is as follows:
I have a webserviceclass.asp that helps me consume web services in classic asp.
code of webserviceclass.asp -> https://docs.google.com/file/d/0B1Wr1Kw74xy3ZkducEtiTWNtWDA/edit?usp=sharing
Then calling the class to consume the method.
Dim strWebServiceResult
Dim ws
Set ws = new webservice
ws.url = "http://www.myurl.com/mywebservice.asmx"
ws.method = "HelloWorld"
ws.parameters.Add "Parameter1", "Test1"
ws.parameters.Add "Parameter2", "Test2"
ws.Execute
strWebServiceResult = ws.response
This works perfectly if www.myurl.com is not encrypted, strWebServiceResult holds the XML returned by mywebservice.asmx, however I really need the data traveling between the users and www.myurl.com to be encrypted (mywebservice.asmx has parameters for login and password to authenticate on the webservice) so I bought an SSL cert and assigned it to www.myurl.com website becoming https://www.myurl.com
So when I set the URL in the class to: ws.url = "https://www.myurl.com/mywebservice.asmx"
and that is the only thing that changes, the method doesn't get called anymore. I have log on pageinit and pageload of the mywebservice.aspx and it doesn't even get called.
Sorry about the long text, and I hope someone can help me. I have no experience with jquery or json and I'd rather not go that way to solve this problem, but if that's the only way, I can try if there's enough info out there to help me out but I'd rather try to fix my current code if that possible. I just don't understand why it works with http but not with https
Many thanks in advance
In this SO question ("Can't use HTTPS with ServerXMLHTTP object"), this issue was addressed.
For a starter, you should be using "MSXML2.ServerXMLHTTP" instead of "Microsoft.XMLHTTP" on the server side. This is discussed here, f.i.: differences between Msxml2.ServerXMLHTTP and WinHttp.WinHttpRequest?
I've read a lot about switching between multiple datasource on runtime, but as far as I understand they're already defined datasources. I'm not quite sure on how can I just asign the datasources properties on runtime from a webservice call.
I don't need to switch between datasources, just need to create only one datasource with conection data coming from a webservice.
Is there a way to retrieve these parameters from the webservice and create the datasource from that?
The policy here is to retrieve the datasource parameters from a webservice for all the projects, that way the connection data is not inside a file nor into the code, and is only manipulated by DBAs from a global security aplication.
I tried to call the web service in the same datasource file, but it didn't work.
Info:
Web service is a Soap Web service
Grails: 1.3.9
Regards.
I think that you can create a BeanPostProcessor that take care of calling your webservice and changing the settings of your dataSource.
Probably you will need to delay the session factory creation, making sure Grails won't try to use your dataSource before you have all setted up correctly.
The BeanPostProcessor will looks like:
class WebserviceDataSourceBeanPostProcessor implements BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean
}
Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof DataSource){
def info = //call webservice here...
bean.username = info.username
bean.password = info.password
bean.url = info.url
//checkout more setters in: http://commons.apache.org/proper/commons-dbcp/apidocs/org/apache/commons/dbcp/BasicDataSource.html
}
return bean
}
}
And make sure you declared this Spring Bean in resources.groovy
beans = {
webserviceDataSourceBeanPostProcessor(WebserviceDataSourceBeanPostProcessor)
}
If you will have more than one project with this same config comming from a webservice you may think in the possibility of a plugin for this, reusing your code.
I am trying to set some session information in one web method and return it in another web method, but the session data is always empty on the second web method. Here is what I tried
Web Method 1 - Sets session information
Method StartSession() As %String [WebMethod]
{
set %session.NewSession = 1
set %session.Data("key") = "dude"
Quit "Session Started"
}
Web Method 2 - Gets session information should return dude, but is returning blank
Method TestSession() As %String [WebMethod]
{
Quit $Get(%session.Data("key"))
}
To use sessions with Cache web services you need to set the SOAPSESSION class parameter of your web service class equal to 1.
Doing so will cause the web service to return a SOAP session header in the response. If you are using a client that was built to expect this header you may not need to set up anything else. Otherwise, your client application will have to read this header and include it in all further requests, so the server can know which session you are using. An example of this header given in the documentation is:
<csp:CSPCHD xmlns:csp="http://www.intersystems.com/SOAPheaders">value of
CPSCHD token</csp:CSPCHD>
Note that security is a separate issue that your example doesn't address.
Also note that Intersystems has decided that web services will continue to use a license for some period of time after the call has been made. I can't find documentation on this, and I believe it's something like a few seconds per call. I believe that this can cause license issues that would not occur if you used other software to provide web services, and had that other software call Cache via some mechanism other than web services. I believe this is true even when that other software carefully follows all the rules in the license agreement about named and anonymous users. However, I'm not certain about any of this licensing stuff. Still, you might want to do some testing before you commit to an architecture.
As an alternative to psr's answer another way to handle state is to use custom SOAP headers.
For example:
Create a class for your custom SOAP headers like below:
Class Headers.TimeStamp Extends %SOAP.Header
{
Property TimeSent As %TimeStamp;
}
In the web method do this:
set h=##class(Headers.TimeStamp).%New()
set h.TimeSent=$ZTIMESTAMP
do ..HeadersOut.SetAt(h,"Timestamp")
This will generate the following SOAP header:
<SOAP-ENV:Header>
<TimeStamp xmlns:hdr="http://www.myapp.org">
<TimeSent>60712,70996.027Z</TimeSent>
</TimeStamp>
</SOAP-ENV:Header>
This will allow state to be maintained within the SOAP headers rather than using Cache's session management.
DotNetNuke 6.2 has a Services Framework that does something similar
http://www.dotnetnuke.com/Resources/Wiki/Page/DotNetNuke-6-2-Developer-Quick-Start.aspx#Services_Framework_18
The single biggest convenience of Services Framework is that authentication, authorization and establishing a DotNetNuke context are all built in.
How do I integrate ServiceStack (http://servicestack.net) with DotNetNuke to provide authentication, authorization and establish a DotNetNuke context? Any pointers?
I wrote the DNN implementation, so I can tell you about how it works. I don't know the details of ServiceStack so I can't tell you how to apply it there. When I first set out to build this, I expected it to be much more complicated than it actually is. You really only need a handful of calls into the core.
Establishing context and authentication occurs during initialization of the DnnController. One of the great things about DNN being all open source is that all these sort of details are public. Here is a link to the DnnController.cs
And here are the most interesting bits:
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
LoadDnnContext(requestContext.HttpContext);
AuthenticateRequest(requestContext.HttpContext, PortalSettings.PortalId);
}
protected virtual void AuthenticateRequest(HttpContextBase context, int portalId)
{
if (!context.Request.IsAuthenticated)
{
BasicAuthenticator.Instance.TryToAuthenticate(context, portalId);
}
if (!context.Request.IsAuthenticated)
{
DigestAuthenticator.Instance.TryToAuthenticate(context, portalId);
}
MembershipModule.AuthenticateRequest(context, true /*allowUnknownExtension*/);
}
protected virtual void LoadDnnContext(HttpContextBase context)
{
var domainName = TestableGlobals.Instance.GetDomainName(context.Request);
var alias = TestablePortalAliasController.Instance.GetPortalAliasInfo(domainName);
int tabId;
ValidateTabAndModuleContext(context, alias.PortalID, out tabId);
var portalSettings = new PortalSettings(tabId, alias);
context.Items["PortalSettings"] = portalSettings;
}
The Service Framework forces all routes into the form {unique portal path}/DesktopModules/{ModuleName}/API/{url} . The unique portal path is important to easily identifying the portal to which the request was sent. In most cases DNN will allow a URL of the form /Default.aspx?portalid=n, but Service Framework won't accept that, it requires that the request path match the portal alias e.g. mysite.com/childportal/... This requirement ensures that GetDomainName() will work.
I should mention that the TestableXXX classes are in the Internal namespace and therefore are not part of the official public API, and are subject to breaking changes between releases. Most of the methods on the classes have a public analog which is harder to mock but otherwise equivalent. If it is reasonable for you to make small code fixes before upgrading your servers, feel free to use the Testables. If you don't have complete control over the upgrades of your servers you should avoid the .Internal namespaces.
Service Framework supports authentication against the permission of a specific module instance. Services tied to a module must provider tab and module ids. If your services are not module specific you may omit this, and use a tabid of -1 in the PortalSettings.
ServiceFramework has it's own implementations of basic and digest auth since MVC does not provide them. I beleive that ServiceStack does provide Basic and Digest, so you probably only need to make the call to MembershipModule.AuthenticateRequest().
I use an IOC container which provides me with IService.
In the case where IService is a WCF service it is provided by a channel factory
When IService lives on the same machine it is able to access the same cookies and so no problem however once a WCF Service is called it needs to be sent those cookies.
I've spent a lot of time trying to find a way to send cookies using a channel factory and the only way I could find that works is the following
var cookie = _authenticationClient.GetHttpCookie();
HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers.Add(HttpRequestHeader.Cookie, cookie.Name + "=" + cookie.Value);
using(var scope = new OperationContextScope((IClientChannel)_service))
{
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
var result = _service.Add(details);
if (result.Result == RPGResult.Success)
{
return RedirectToAction("Index", "Home", result.Id);
}
}
The problem with me using that method is that I have to know that I'm calling a WCF Service which is not always the case. I've tried writing a wrapper for the ChannelFactory that opens a new operationcontextscope when it creates a new service and various other solutions but nothing has worked.
Anyone have any experience with sending cookies over WCF Services?
I found a solution involving using SilverLight, unfortunately I'm not using silverlight, the solution is here: http://greenicicleblog.com/2009/10/27/using-the-silverlight-httpclient-in-wcf-and-still-passing-cookies/
Unfortunately standard .net doesn't contain the IHttpCookieContainerManager interface
Ideally I would be able to use something similar,i.e. I would be able to tell the channelfactory to pass a cookie whenever it opened.
If anyone has a better way to pass a token that is used for authentication that would be appreciated too.
I have a solution where I create a proxy class of IService and then every time a method on IService is called it invokes the proxy created by the channel factory but the call itself is wrapped in an operationcontextscope just like the one I have in my question.
I used the proxy factory from this link http://www.codeproject.com/KB/cs/dynamicproxy.aspx