HTTPContext for webservices - c#

HttpContext.Current.Request.ServerVariables["SERVER_PORT"]
HttpContext.Current.Request.ServerVariables["SERVER_PORT_SECURE"]
HttpContext.Current.Request.ServerVariables["SERVER_NAME"]
HttpContext.Current.Request.ApplicationPath
I want to access these value via a webservice -C#, whenever I call these values in webservice I get null for all of the above, where as above works for web pages (aspx).

As others have mentioned, you need to enable ASP.NET compatibility. You can also enable this via configuration if you don't want to limit your code via attributes like so:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
Here's a great resource that helped explain to me the underlying functionality and trade-offs made by enabling compatibility mode.

What sort of web service are you using? asmx or wcf? They should work fine with asmx services but if you're using WCF, you'll need to add the following attribute to the method:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

have you tried to define your method with EnableSession at true?
[WebMethod(EnableSession = true)]
public string your_public_method(your_params)
{ [...] }

If it is a WCF web service you can do the following:
[AspNetCompatibilityRequirementsAttribute(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class FooBar : IFooBar
{
public void DoSomething()
{
HttpContext context = HttpContext.Current;
if (context != null)
{
// Should get here now
}
}
}
The key is to add [AspNetCompatibilityRequirementsAttribute(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)].

Related

Proxy for interacting with WCF services on client

Please, Help me !
I've some problems with my project (WPF with WCF).
My project its client-server interaction. In server I've EF that interaction with PatternRepository . On server it`s a wcf interaction I have services.
Each service its repository. In each service I have a set of commands for communication between server and client . Between client and server data transfer occurs via Json . Example, it's service:
public class ProductRepositoryService : IProductRepositoryService
{
public void AddProduct(string json)
{
_productRepository.Add(wrapperProduct.DeserializeProduct(json));
_productRepository.Save();
}
public void DeleteProduct(string json)
{ productRepository.Delete(_productRepository.GetById(wrapperProduct.DeserializeProduct(json).Id));
_productRepository.Save();
}
}
Example, its ProductSeviceLogics that interaction with ProductService :
ProductRepositoryServiceClient _service1Client;
public ProductSeviceLogics()
{
this._service1Client = new ProductRepositoryServiceClient();
}
public void AddProduct(string json)
{
_service1Client.AddProduct(json);
}
public void DeleteProduct(string json)
{
_service1Client.DeleteProduct(json);
}
It's mean that if I'll create services. I'll be create those methods for each service on the server and the client. I think that it's very bad .
So my question, How can i do so that these methods will be for all services ?
That is, I want not to create this methods for each service and for each client.
I recommend you to have a look into this ASP.NET MVC Solution Architecture article. Download the code and have a look into that, how they maintain the Repositories/Services/Models in separate class library and make use in User interface or WCF or WebAPI.
Here I will provide some sample solution pattern.
Create a new blank solution : File -> New Project -> Other Project Type -> Blank Solution and name it as MyProject.
Create new class library listed below
MyProject.Model
Create POCO class like Product, Sale
MyProject.Data
Add a reference of Model.
Contains EF(DbSet and DbContext) and Repositories like ProductRepository, SalesRepository.
MyProject.Service
Add reference Model and Data.
Make a call to your repositories from this project.
Create User Interface and WCF services
MyProject.Web
MyProject.WCF
Add a reference of Model and Service.
Your work flow like this WCF or Web Calls --> Service --> Repositories --> EF, So you can avoid creating multiple service for client and server.
Hope this helps you.
I solved this issue.
Generate proxy for WCF Service
Generate Proxy by implementing ClientBase class*
Generating proxy by using ClientBase class option has an advantage that it creates proxy at run time, so it will accommodate service implementation changes. Let’s follow the steps to generate proxy.
Add a Client Project to solution named as “ClientApp2″ that is
basically a Console Application.
enter image description here
Add reference of StudentService Project to ClientApp2. Add following
proxy class using ClientBase as:
public class StudentServiceProxy : ClientBase<IStudentService>, IStudentService
{
public string GetStudentInfo(int studentId)
{
return base.Channel.GetStudentInfo(studentId);
}
}
Note: Don’t forget to add “using StudentService” to class.
Following is the code for program.cs class in ClientApp2. We are using above created proxy class to communicate with WCF Service
“StudentService“.
class Program
{
static void Main(string[] args)
{
StudentServiceProxy myclient;
myclient = new StudentServiceProxy();
int studentId = 1;
Console.WriteLine(“Calling StudentService with StudentId =1…..”);
Console.WriteLine(“Student Name = {0}”, myclient.GetStudentInfo(studentId));
Console.ReadLine();
}
}
Note: Don’t forget to add “using System.ServiceModel” to class.
App.Config file will have following configuration:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name=”WSHttpBinding_IStudentService” />
</wsHttpBinding>
</bindings>
<client>
<endpoint address=”http://localhost:4321/StudentService”
binding=”wsHttpBinding”
bindingConfiguration=”WSHttpBinding_IStudentService”
contract=”StudentService.IStudentService”
name=”WSHttpBinding_IStudentService”>
</endpoint>
</client>
Now, when we run the client application, we will receive the following same output as we get in earlier option “Adding Service Reference”.

Rest + WCF Integration for Xamarin Forms

I am doing a Xamarin Forms project that requires connection to a WCF service. I must use Rest to access it, so I opted to use a PCL-compatible build of RestSharp. I have done many SOAP based web services, but this is my first dive into Rest, and I feel like I am missing something very basic. I have confirmed that my web service functions correctly when I make SOAP calls, so I believe I have set something up incorrectly.
Here is sample code for my web service:
Imports System.IO
Imports System.Net
Imports System.ServiceModel
Imports System.ServiceModel.Description
Imports System.ServiceModel.Web
<ServiceContract()>
Public Interface Iapi
<WebInvoke(Method:="PUT",
UriTemplate:="Login/Email/{Email}/Password/{Password}",
RequestFormat:=WebMessageFormat.Json,
ResponseFormat:=WebMessageFormat.Json)>
<OperationContract(AsyncPattern:=True)>
Function Login(email As String, password As String) As String
End Interface
Here is sample code for my attempt to call the service:
public void Login(string email, string password)
{
RestClient client = new RestClient("http://www.example.com/service.svc/");
RestRequest request = new RestRequest
{
Method = Method.PUT,
Resource = "Login/Email/{Email}/Password/{Password}",
RequestFormat = DataFormat.Json
};
request.AddParameter("Email", email, ParameterType.UrlSegment);
request.AddParameter("Password", password,ParameterType.UrlSegment);
client.ExecuteAsync(request, response => {
session = response.Content;
ActionCompleted(this, new System.EventArgs());
});
}
When I make the call above, I get no exceptions, just an empty string return value. The same thing happens in the browser. I suspect my service definition. I have several questions that are probably a bit basic, but I hope will also help other WCF/Rest beginners in the future.
1. What, if anything, is wrong with my UriTemplate in the definition of my service? What would a proper UriTemplate look like?
2. Should I be using the PUT method for this kind of service call, or is GET or POST more appropriate?
3. Is anything else obviously missing from my web service definition?
4. Am I correct in passing the full service uri (http://www.example.com/service.svc/) to the Rest client?
5. Any additional suggestions for a Rest beginner, specifically in relation to the WCF-Rest combination?
A proper URI-template could look something like this if you're using a GET:
C#
[OperationContract]
[WebGet(UriTemplate = "Book/{id}")]
Book GetBookById(string id);
VB:
<OperationContract()> _
<WebGet(UriTemplate:="Book/{id}")> _
Function GetBookById(ByVal id As String) As Book
Then you can call it using http://example.com/Book/1 for the book with ID==1.
In the Microsoft-world PUT is often used for creating or updating data, such as a new task, order etc. However, you CAN use it for login even if I personally think a POST or GET would be the more accurate approach. But that's just my oppinion.
See this question for more information:
PUT vs POST in REST
There's nothing that seems to be missing in you declaration.
If you cannot reach it with a browser, it's probably not the usage of RestSharp that's wrong. However, here's some notes. When using async methods you will often want to try using .NET's async/await-pattern. Then the request doesn't lock the main thread.
Example:
http://www.dosomethinghere.com/2014/08/23/vb-net-simpler-async-await-example/
Here's a little piece of code that I use in my Xamarin-projects for invoking services:
protected static async Task<T> ExecuteRequestAsync<T>(string resource,
HttpMethod method,
object body = null,
IEnumerable<Parameter> parameters = null) where T : new()
{
var client = new RestClient("http://example.com/rest/service.svc/");
var req = new RestRequest(resource, method);
AddRequestKeys(req);
if (body != null)
req.AddBody(body);
if (parameters != null)
{
foreach (var p in parameters)
{
req.AddParameter(p);
}
}
Func<Task<T>> result = async () =>
{
var response = await client.Execute<T>(req);
if (response.StatusCode == HttpStatusCode.Unauthorized)
throw new Exception(response.Data.ToString());
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception("Error");
return response.Data;
};
return await result();
}
Yes, that's correct.
How do you host your WCF? If using IIS, what does your web.config look like? Here's an example:
As a side note, I noticed you mentioned that you require access to a WCF-service. Have you considered using .NET Web API instead? It provides a more straight-forward approach for creating RESTful endpoints, without the need for configs. It's more simple to implement and to use, however it does not provide the same flexibility as a WCF-service does.
For debugging a WCF-service I strongly recommend "WCF Test client":
https://msdn.microsoft.com/en-us/library/bb552364(v=vs.110).aspx
Where can I find WcfTestClient.exe (part of Visual Studio)
With metadata-enabled in your web.config, you will be able to see all available methods. Example-configuration below:
<configuration>
<system.serviceModel>
<services>
<service name="Metadata.Example.SimpleService">
<endpoint address=""
binding="basicHttpBinding"
contract="Metadata.Example.ISimpleService" />
</service>
</services>
<behaviors>
</behaviors>
</system.serviceModel>
</configuration>
Source:
https://msdn.microsoft.com/en-us/library/ms734765(v=vs.110).aspx
If it doesn't help, could you provide your web.config and implementation of your service as well?

Disable metadata exchange without using web.config

I am developing a single-tenant web application that will be deployed in client data centers and for security reasons we would like to disable the metadata exchange on the applications WCF services. Is it possible to do this this programatically within our service application or another mechanism besides the web.config? We want to prevent more technically minded clients from going to the web.config and turning metadata exchange back on.
You can disable the metadata exchange programmatically by setting the HttpGetEnabled/HttpsGetEnabled to false.
First, Create a derive host from ServiceHost.
public class DerivedHost : ServiceHost
{
public DerivedHost( Type t, params Uri baseAddresses ) :
base( t, baseAddresses )
{
DisableMetadataExchange();
}
private void DisableMetadataExchange()
{
var metadata = Description.Behaviors.Find<ServiceMetadataBehavior>();
if metadata != null)
{
// This code will disable metadata exchange
metadata .HttpGetEnabled = false;
metadata .HttpsGetEnabled = false;
}
}
}
Second, Create a derived factory from ServiceHostFactory.
public class DerivedFactory : ServiceHostFactory
{
public override ServiceHost CreateServiceHost( Type t, Uri[] baseAddresses )
{
return new DerivedHost( t, baseAddresses );
}
}
Third, Create or Edit your your svc file Markup and apply your derived factory.
<% #ServiceHost Factory=”DerivedFactory” Service=”MyService” %>
Fourth, Test your service in the browser and you should see a message contain "Metadata publishing for this service is currently disabled".
If want more details about this implementation kindly visit this link.
Yes. If you code your WCF service as "self describing", which basically means using a WCF intercept layer to handle all the incoming requests to an endpoint, you can just return null from the MEX request.
To make this work is a bit tricky but in my experience leads to a much cleaner implementation than all those voluminous web.config entries. This is described here WCF Configuration without a config file.

Creating a custom .svc handler for WCF service hosted in IIS

I am hosting a wcf service in IIS 7. I was curious if it would be possible to create my own .svc HttpHandler mapping and class to handle service requests.
For example, if I was to intercept any requests to files that ended with an extension of ".foo" I could add this to my web.config
<handlers>
<add name="*.foo_**" path="*.foo" verb="*" type="MyServer.FooHttpHandler" />
</handlers>
And I could have a class in my default root that did the following
public class FooHandler: IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// do stuff, validate?
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("filename={0}", url));
HttpContext.Current.Response.AddHeader("Content-Type", "fooMimeType");
HttpContext.Current.Response.WriteFile(url);
HttpContext.Current.Response.End();
}
public bool IsReusable
{
get { return false; }
}
}
Is it possible to do something like this with wcf .svc requests? I'm not sure if it'd be the exact same thing or not, since I'm not necessary serving a file to respond with, I want to intercept and proxy the response.
Or is a better way to implement a service behavior that does my required pre-service logic?
What are you trying to achieve? Not sure if you can replace the existing *.svc http handler - but what you can do much more easily is create your own custom ServiceHostFactory for the WCF service. You basically add one attribute your *.svc file:
<%# ServiceHost Language="C#" Debug="true"
Service="YourNamespace.YourService"
Factory="YourNamespace2.YourServiceHostFactory" %>
Using this, IIS will now instantiate your own YourServiceHostFactory and ask you to create an instance of the YourService class. Maybe you can hook into the flow here and do what you need to do?
You could use ASP.NET Routing and an IRouteHandler that returns your own IHttpHandler implementation as well if you really want to as well
http://msdn.microsoft.com/en-us/library/system.web.routing.iroutehandler.gethttphandler.aspx
http://msdn.microsoft.com/en-us/library/cc668201.aspx
I've done this in the past when setting up WCF Data Services and I don't see why it can't work here as well.

Securing WCF services using ASP.NET Auth and a DomainService with Silverlight

I have the basic ASP.NET authentication domain service running in my Silverlight app (the one that comes with the VS2010 Silverlight Business template).
How can I use the authentication that this grants to secure methods exposed by standard WCF services (also hosted in the same app in IIS)?
Ok, so this is how you do it, the standard WCF service needs a couple of attributes, and you need to assign the Thread.CurrentPrincipal:
[ServiceContract(Namespace = "")]
[SilverlightFaultBehavior]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1
{
public Service1()
{
Thread.CurrentPrincipal = HttpContext.Current.User;
}
[OperationContract]
[PrincipalPermission(SecurityAction.Demand, Role = "Registered Users")]
public string DoSomeWork()
{
return "working";
}
}
A good place to start is here: Security for WCF RIA Services. What you're looking for is the RequiresAuthentication attribute.
[RequiresAuthentication]
public Foo SomeMethodCall(object parameter1)
{
return service.GetResult(parameter1)
}

Categories

Resources