Web service and global parameter - c#

I start building a new web service for my app and i want to make a global int for example that every time someone call this web service this int will increase in one.
this is what i create in visual studio:
public partial class Form : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
and i try to put static int in the class but it not work.

Put your variable in Application state.
Note you need to make it thread safe.
from http://msdn.microsoft.com/en-us/library/94xkskdf(VS.80).aspx
Application.Lock();
Application["PageRequestCount"] =
((int)Application["PageRequestCount"])+1;
Application.UnLock();

Related

Global objects in C# ASP.Net - always null when read back

In an ASP.Net project, using C#, I have a class (PlcComms.cs) for talking to a Controller (a PLC).
I want the one class object to be globally available, for each web page in my project.
I see from reading various forum posts that I should be able to create a public static object of my class type, i.e. PlcComms, in Global.asax.cs, or in a class in the App_Code folder. I've tried both and I write to the object ok, but when I go to read from it (from a timer in an update panel on the home web page) then it always read back as null.
I'm at a loss to know what to do at this point. can anyone help?
Currently, this is a class I have in the App_Code folder...
namespace SpearheadWeb
{
public static class AppGlobal
{
public static SpearheadWeb.PlcComms PlcCommsObject { get; set; }
}
}
this I have on my web page - it seems to create the object OK...
namespace SpearheadWeb
{
public partial class _Default : Page
{
private PlcComms CurrentPLC;
//some other here including ComPorts
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
try
{
//some settings reading and setup here
CurrentPLC = new PlcComms(Global.CommsSettings.CpuType1,Global.CommsSettings.Network1,ComPorts[0], Global.CommsSettings.IPAddress1, Global.CommsSettings.Path1,UpdatePanel.Controls[0].Controls, 1, Global.CommsSettings.MsUpdate1);
AppGlobal.PlcCommsObject = CurrentPLC;
but in my timer (the timer within an updatepanel) PLCComms1 is always null here...
protected void TimerUpdate_Tick(object sender, EventArgs e)
{
PlcComms PLCComms1 = AppGlobal.PlcCommsObject;

WCF test/Smoke test

I wish to have a test to insure my WCF service is up and running.
I found this:
[OperationContract]
public void Ping(){}
I put that in my IService, but not the Service.svc?
How do I know it works? Do I put in a button and a text box in my User Interface that calls this method, and have some sort of statement in that ping method that places a value in the text box if that Ping method runs? Here is what I propose:
IService:
[OperationContract]
public void Ping()
{
TextBox.Text = "Okay".ToString();
}
User Interface:
private void btnPing_Click(object sender, RoutedEventArgs e)
{
public void Ping()
}
For testing your WCF service up and running make a windows form(as you have previously done)
Write click on project/solution and choose Add service reference.
Paste your service url in address textbox (Ex. www.xyz.com/abcservice.svc or www.xyz.com/true?wsdl) Change the namespace in same wizard.(default would be ServiceReference1).
Now use your button click event as what your were doing then call this method.
private void btnPing_Click(object sender, RoutedEventArgs e)
{
ServiceReference1.yourServiceClassName obj = new ServiceReference1.yourServiceClassName();
obj.ping();
//Check your output if that is not throwing any exception.
}
If no error or exception then everything is OK.

Thread doesn't seem to be running in the background

I have the following code:
public class BaseControlClass : System.Web.UI.UserControl
{
protected delegate void AsyncronousAction();
protected virtual void FAsyncEvent() { } //Overidden on derived classes.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
FPerformAsyncronousTasks(FAsyncEvent);
}
protected virtual void FPerformAsyncronousTasks(AsyncronousAction AsyncCallback)
{
new Thread(delegate()
{
AsyncCallback();
}).Start();
}
}
public class DerivedControlClass : BaseClass
{
protected override void FAsyncEvent()
{
//Contact web service, wait for results, add to local database.
}
}
What I was expecting is for the page to load and the code in FAsyncEvent() in my derived class to run behind the scenes however, the page doesn't finish loading until the code in FAsyncEvent() has completed.
Am I doing something wrong with the threading here?
EDIT Strangely, I have noticed if I do a Clean -> Build then run the code, it works fine and the page finishes loading whilst the web service is being contacted. Subsequent runs though mean the page waits until the thread has finished processing.
Your code keeps the reference to the UserControl alive, which might be preventing the request from continuing. Try passing a static method to the new thread, just as a quick check and see if it helps.

Calling a Web Method from ASPX Code Behind

I'm trying to figure out a way that I can call a Web Method (located as a public static method in the code behind of an aspx page) from another ASPX Code Behind page.
This is the code behind of Page A.aspx
public partial class PageA : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// other code not relevant is here
}
[WebMethod(true)]
public static string GetStringInfo()
{
// do some stuff here to build my string
// return string
}
}
On page B, I need to be able to call GetStringInfo() during page load or some other event to get the information. the GetStringInfo() is fairly complex and for reasons outside of my control, can't be moved elsewhere or rebuilt presently.
How can I consume the web method above from another page's code behind?
I've tried instantiating a copy of the other page (PageB), such as:
public partial class PageB : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
PageA page = new PageA();
page.GetStringInfo();
}
}
The problem here is since it's dynamically compiled, I don't have an easy namespace to reference and access. I've tried adding one, and it ignores it.
This project is on .net 3.5, C#, and is a web site project (not a web application).
Any help is appreciated!
If the GetStringInfo method is static you don't need an instance of PageA to invoke it:
public partial class PageB : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string info = PageA.GetStringInfo();
}
}

WCF client in ASP.net Page

Can anyone advise of a good pattern for using a WCF Service from an ASP.net Page? It seems that if the lifetime of the Client(:ServiceModel.ClientBase) is not properly controlled that we get PipeException thrown. It currently exists as a field of the Page class, but is being reinstantiated upon each page request without being cleaned up (the .Close method).
I suspect this question could be rephrased "Managing limited resources in an ASP.net page", and is probably more related to the lifecycle of an ASP.net page. I'm new to ASP.net, so my understanding of this is a little thin.
TIA.
EDIT: Some code (there's not much to it!)
public partial class Default : Page
{
//The WCF client... obviously, instantiating it here is bad,
//but where to instantiate, and where to close?
private readonly SearchClient client = new SearchClient();
protected void Page_Load(object sender, EventArgs e)
{
2nd Edit: Would the following be better?
public partial class Default : Page
{
private SearchClient client;
protected void Page_Unload(object sender, EventArgs e)
{
try
{
client.Close();
}
catch
{
//gobbled
}
}
protected void Page_Load(object sender, EventArgs e)
{
client= new SearchClient();
//.....
I agree with Michael, abstract it out into another layer if possible.
However, if you are going to call it from your aspx page, I would just create a separate method to call it, return its results and cleanup. Keeps the code clean by having it all in one place. Just remember to dispose in your finally block, and that the wcf proxy will have to be cast to IDisposable in order to dispose.
for instance:
void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
RemoteCall();
}
}
void RemoteCall()
{
var client = new SearchClient();
try
{
var results = client.Search(params);
clients.Close();
}
catch(CommunicationException cex)
{
//handle
}
catch(Exception ex)
{
//handle
}
finally
{
((IDisposable)client).Dispose();
}
}
In general, you shouldn't call external services directly from your presentation tier. It creates two problems: first, performance (pooling, scaling, etc), and second, it creates a security risk if you need to authenticate (authentication code in your DMZ is bad.
Even if you don't have an application tier, you should consider refactoring your service call to a private service in your presentation tier. This will allow you to decouple the service's lifecycle from the page's lifecycle (which is problematic as you have stated).

Categories