Dynamic Web Service URL with MonoTouch - web-services

I have an app written using MonoTouch that relies on a Web Services URL backend. I need the ability to set the URL of this backend dynamically at run time from within the app (or from within it's settings).
I've read this article on CodeProject that describes setting URL dynamically:
http://www.codeproject.com/Articles/12317/How-to-make-your-Web-Reference-proxy-URL-dynamic#_rating
But I can't find this option in MonoDevelop.
I've tried altering the Url property of my service, but it appears there is more to it than that. (Specifically the "references.cs" file added by the web service seems to also have the URL hard coded in various attributes).
Any help much appreciated.
Thanks!
--scotru

When Mono generates C# wrapper for SOAP web-service to you, it creates 2 constructors of wrapper. Second one contains URL parameter, which you can use to set proper URL and so switch between web-services.
Example from project, which is in production (file Reference.cs):
public partial class ServicesInfoImplService : System.Web.Services.Protocols.SoapHttpClientProtocol
...
public ServicesInfoImplService() {
this.Url = "<DEFAULT_URL>";
}
public ServicesInfoImplService(string url) {
this.Url = url;
}
...

Related

How to open JSF page using JAX-RS web service?

I would like other web application (in .net or any other) to call my JAX-RS web service to set and open my JSF page with some passed values.
E.g.
Another web application just pass the userId and a token to open an entry page.
User will complete the entry and service will return the uniqueId for created entry.
I am confused in how I can set JSF context parameters and open that JSF page using JAX-RS. Can anyone give idea about how to set value of JSF session scoped managed bean using web service?
First of all, this question indicates a misunderstanding of purpose of "REST web services" in general. The question concretely asks to perform two rather unusual tasks with a REST web service:
Manipulating the HTTP session associated with the request.
Redirecting to a HTML page managed by a stateful MVC framework as response.
Both squarely contradict the stateless nature of REST. Those tasks aren't supposed to be performed by a REST web service. Moreover, REST web services are primarily intented to be used by programmatic clients (e.g. JavaScript or Java code), not by webbrowsers which consume HTML pages. You normally don't enter the URL of a REST webservice in browser's address bar in order to see a HTML page. You normally enter the URL of a HTML page in browser's address bar. That HTML page can in turn be produced by a HTML form based MVC framework such as JSF.
In your specific case, after the programmatic client has retrieved the unique
ID from the REST web service, then the programmatic client should in turn all by itself fire a new request to the JSF web application. E.g. as follows in Java based client (below example assumes it's a plain servlet, but it can be anything else as you said yourself):
String uniqueId = restClient.getUniqueId(userId, token);
String url = "http://example.com/context/login.xhtml?uniqueId=" + URLEncoder.encode(uniqueId, "UTF-8");
response.sendRedirect(url);
In the target JSF web application, just use <f:viewParam>/<f:viewAction> the usual way in order to grab the unique ID and perform business actions based on that. E.g. as below in login.xhtml:
<f:metadata>
<f:viewParam name="uniqueId" value="#{authenticator.uniqueId}" />
<f:viewAction action="#{authenticator.check}" />
</f:metadata>
#ManagedBean
#RequestScoped
public class Authenticator {
private String uniqueId;
#EJB
private UserService service;
public String check() {
FacesContext context = FacesContext.getCurrentInstance();
User user = service.authenticate(uniqueId);
if (user != null) {
context.getExternalContext().getSessionMap().put("user", user);
return "/somehome.xhtml?faces-redirect=true";
}
else {
context.addMessage(null, new FacesMessage("Invalid token"));
return null; // Or some error page.
}
}
// Getter/setter.
}
Perhaps the REST webservice could for convenience even return the full URL including the unique ID so that the client doesn't need to worry about the target URL.
String uniqueIdURL = restClient.getUniqueIdURL(userId, token);
response.sendRedirect(uniqueIdURL);
On the other hand, there's a reasonable chance that you just misunderstood the functional requirement and you can just directly process the user ID and token in the JSF web application, the more likely if it runs at the same server as the REST web service and also uses HTTPS. Just add an extra <f:viewParam> and do the same business service logic as the JAX-RS resource in the <f:viewAction> method.
<f:metadata>
<f:viewParam name="userId" value="#{authenticator.userId}" />
<f:viewParam name="token" value="#{authenticator.token}" />
<f:viewAction action="#{authenticator.check}" />
</f:metadata>
See also:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
How to implement JAX-RS RESTful service in JSF framework
Try this in your code,
return new Viewable("/index", "FOO");
Or,
RequestDispatcher rd = request.getRequestDispatcher("{url}");
rd.forward(request, response);
Or,
return Response.status(myCode).entity(new Viewable("/index", "FOO")).build();
try these example working in using jersey,
#GET
public Response get() {
URI uri=new URI("http://nohost/context");
Viewable viewable=new Viewable("/index", "FOO");
return Response.ok(viewable).build();
}
to return something different use this approach:
#GET
public Response get() {
int statusCode=204;
Viewable myViewable=new Viewable("/index","FOO");
return Response.status(statusCode).entity(myViewable).build();
}
Hope that helpe

Jaggery (WS02) endpoint reference/dynamic endpoint

I'm currently developing an application in Jaggery which I deploy on their API manager.
From the Jaggery back end I'm calling a SOAP webservice using the method documented here, which specifies:
<%
var url = 'http://jaggeryjs.org/apidocs/resources/home.jag';
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.setRequestHeader("user" , "madhuka");
xhr.send();
print("ReadyState : "+xhr.readyState);
print("<br>ResponseStatus : "+xhr.status);
print("<br>ResponseText : "+xhr.responseText);
%>
I have everything up and working fine, however I'd like to remove the hard-coded URL and replace it with some sort of URL lookup, based on environment.
What is the correct way of doing this? Can I specify an endpoint in API manager and refer to it? Or perhaps use an EPR file. I've had little luck with the Jaggery documentation in this sense.
I have seen many jaggery apps developed for WSO2 products. The practice followed in them is to have a config file in json format. You can have a method to read it and get necessary values by passing the attribute name.
You can either have a config file for each environment and pack the correct one with the app or have a single config file with endpoints for each environment. If you are going to maintain a single config file, you have to dynamically construct the attribute name and read its value. To do that also, you need to maintain which environment it is. Therefore I recommend to use a config file for each environment and bundle the correct file for the environment.

Issue Identifying resource URI - Restful web services

I am working on an application that uses rest webservices where a uri has been invoked from a .js file.
var invokeWS = "/resource/domain/program/tasks";
jQuery.getJSON(invokeWS ,data)
While looking at all the jar's I found out that the class corresponding to program is present in a package "com.company.project.webapps.util.rest.service" as below
package com.company.project.webapps.util.rest.service;
#Path("/program")
public class Program extends RS
{
#Path("/tasks")
#GET
public get...()
{
}
}
I do not see any mapping url in web.xml but the the webservice call made through .js would some how pick the correct path and invokes the service.
Can you please let me know if this can be achieved in a any other way as I do not see any entries in web.xml of the applicaiton.
Thanks
Awanish

Am I reinventing the wheel with this ASP.NET Web API based webserver?

In a standalone (selfhosted) application, I would like to have an httpserver that on a single base adress can either serve simple web pages (without any serverside dynamics/scripting, it just returns the content request files) or serve RESTful webservices:
when http://localhost:8070/{filePath} is requested, it should return the content of the file (html, javascript, css, images), just like a normal simple webserver
everything behind http://localhost:8070/api/ should just act as a normal RRESTful Web API
My current approach uses ASP.NET Web API to server both the html pages and the REST APIs:
var config = new HttpSelfHostConfiguration("http://localhost:8070/");
config.Formatters.Add(new WebFormatter());
config.Routes.MapHttpRoute(
name: "Default Web",
routeTemplate: "{fileName}",
defaults: new { controller = "web", fileName = RouteParameter.Optional });
config.Routes.MapHttpRoute(
name: "Default API",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });
The WebController is the controller that serves the web pages with this naive code:
public class WebController : ApiController
{
public HttpResponseMessage Get(string fileName = null)
{
/// ...
var filePath = Path.Combine(wwwRoot, fileName);
if (File.Exists(filePath))
{
if (HasCssExtension(filePath))
{
return this.Request.CreateResponse(
HttpStatusCode.OK,
GetFileContent(filePath),
"text/css");
}
if (HasJavaScriptExtension(filePath))
{
return this.Request.CreateResponse(
HttpStatusCode.OK,
GetFileContent(filePath),
"application/javascript");
}
return this.Request.CreateResponse(
HttpStatusCode.OK,
GetFileContent(filePath),
"text/html");
}
return this.Request.CreateResponse(
HttpStatusCode.NotFound,
this.GetFileContnet(Path.Combine(wwwRoot, "404.html")),
"text/html");
}
}
And again, for everything behind /api, controllers for normal REST APIs are used.
My question now is: Am I on the right track? I kind of feel that I am rebuilding a webserver here, reinventing the wheel. And I guess that there are probably a lot of http request web browsers could make that I do not handle correctly here.
But what other option do I have if I want to self host and at the same time server REST web APIs and web pages over the same base address?
Looks like you are trying to recreate asp.net FileHandler for self host. There is a better solution though. Using Katana(an OWIN host) as the hosting layer for web API. OWIN supports hosting multiple OWIN frameworks in the same app. In your case, you can host both web API and a file handler in the same OWIN app.
Filip has a good blog post on this to get you started here. You can use configuration code like this,
public void Configuration(IAppBuilder appBuilder)
{
// configure your web api.
var config = new HttpConfiguration();
config.Routes.MapHttpRoute("default-api", "api/{controller}");
appBuilder.UseWebApi(config);
// configure your static file handler.
appBuilder.UseStaticFiles();
}
IMO there is nothing wrong with what you are doing. I use self-host for delivering files, html docs as well as being a regular API. At the core, self-host is using HTTP.SYS just as IIS is.
As RaghuRam mentioned there are Owin hosts that have some optimizations for serving static files, but WCF selfhost is quite capable of getting decent perf for serving files.
See this link which uses a more straigftforward approach
Setting app a separate Web API project and ASP.NET app
RouteTable.Routes.IgnoreRoute(".js");
RouteTable.Routes.IgnoreRoute(".html");

How do I integrate ServiceStack and DotNetNuke to provide REST services within a DNN authenticated context?

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().