<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="RSS_xslt_style.asp" version="1.0" ?>
<rss version="2.0" xmlns:WebWizForums="http://syndication.webwiz.co.uk/rss_namespace/">
 <channel>
  <title>DevForce Community Forum : Writing to Server Debug Log from Client</title>
  <link>http://www.ideablade.com/forum/</link>
  <description>This is an XML content feed of; DevForce Community Forum : DevForce 2009 : Writing to Server Debug Log from Client</description>
  <pubDate>Fri, 10 Apr 2026 20:19:05 -700</pubDate>
  <lastBuildDate>Mon, 04 Jan 2010 20:28:28 -700</lastBuildDate>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Web Wiz Forums 9.69</generator>
  <ttl>360</ttl>
  <WebWizForums:feedURL>www.ideablade.com/forum/RSS_post_feed.asp?TID=1481</WebWizForums:feedURL>
  <image>
   <title>DevForce Community Forum</title>
   <url>http://www.ideablade.com/forum/forum_images/IdeaBlade_logo_tm.png</url>
   <link>http://www.ideablade.com/forum/</link>
  </image>
  <item>
   <title>Writing to Server Debug Log from Client : Thanks Ward. </title>
   <link>http://www.ideablade.com/forum/forum_posts.asp?TID=1481&amp;PID=6022#6022</link>
   <description>
    <![CDATA[<strong>Author:</strong> <a href="http://www.ideablade.com/forum/member_profile.asp?PF=651" rel="nofollow">mamadero</a><br /><strong>Subject:</strong> 1481<br /><strong>Posted:</strong> 04-Jan-2010 at 8:28pm<br /><br />Thanks Ward. ]]>
   </description>
   <pubDate>Mon, 04 Jan 2010 20:28:28 -700</pubDate>
   <guid isPermaLink="true">http://www.ideablade.com/forum/forum_posts.asp?TID=1481&amp;PID=6022#6022</guid>
  </item> 
  <item>
   <title>Writing to Server Debug Log from Client : DevForce itself doesn&amp;#039;t have...</title>
   <link>http://www.ideablade.com/forum/forum_posts.asp?TID=1481&amp;PID=6017#6017</link>
   <description>
    <![CDATA[<strong>Author:</strong> <a href="http://www.ideablade.com/forum/member_profile.asp?PF=482" rel="nofollow">WardBell</a><br /><strong>Subject:</strong> 1481<br /><strong>Posted:</strong> 04-Jan-2010 at 5:28pm<br /><br /><P>DevForce itself doesn't have a facility for logging client messages to the server. </P><DIV>What I showed you here is the bare, open-source minimum of a suggestion for doing this yourself in just a few lines. In the real world I would do just as you say and </DIV><DIV>&nbsp;</DIV><DIV>(a) cache log messages in client memory</DIV><DIV>(b) provide a flush-to-server method</DIV><DIV>(c) consider storing on local disk (async of course) in case of crash</DIV><DIV>(d) consider a switch to force flush periodically</DIV><DIV>(e) consider log message filtering</DIV><DIV>&nbsp;</DIV><DIV>These are all things you write yourself with little difficulty. In fact, it should be easy to plug in your own preferred logger that does all that you want on the client side. Then you have to decide how to propagate to the server; you might follow the path hinted at in my post.</DIV><DIV>&nbsp;</DIV><DIV>Our InvokeServerMethod frees you from having to write all the configuration and hook up yourself. It does route through our BOS middle tier server. You won't know if there is a significant&nbsp;performance effect until you measure; then you can decide if this is really a problem. If you want to by-pass the BOS and log to a separate server, you're on your own..</DIV><DIV>&nbsp;</DIV><DIV><strong>Logging is not a central feature of DevForce</strong>. It's an important aid to development; it will not suit many production applications ... nor was that our intention. There are many stronger loggers out there to choose from. In fact, you might want to route our native DevForce server-side log messages&nbsp;to such a logger so you can consolidate feeds from the DevForce server with other log sources. The "how to" of that is a topic for another day (not soon).</DIV><DIV>&nbsp;</DIV><DIV>I have lobbied (to&nbsp;myself)&nbsp;for decoupling DevForce from its own logger. It's nice that we have a logger but you should be able to substitute your own. However, when I put my PM hat on, I can't justify that effort (small as it is) in place of more urgent development. I may revisit that decision if we see enough demand; it stands for now.</DIV><DIV>&nbsp;</DIV><DIV>Seems to me you have a good handle on what you want. I've given you&nbsp;some clues as to how you might proceed on your own. At a minimum, you've got a demo of InvokeServerMethod. </DIV><DIV>&nbsp;</DIV><DIV>Cheers - W</DIV>]]>
   </description>
   <pubDate>Mon, 04 Jan 2010 17:28:58 -700</pubDate>
   <guid isPermaLink="true">http://www.ideablade.com/forum/forum_posts.asp?TID=1481&amp;PID=6017#6017</guid>
  </item> 
  <item>
   <title>Writing to Server Debug Log from Client : Ward, I think a bit more is needed....</title>
   <link>http://www.ideablade.com/forum/forum_posts.asp?TID=1481&amp;PID=5997#5997</link>
   <description>
    <![CDATA[<strong>Author:</strong> <a href="http://www.ideablade.com/forum/member_profile.asp?PF=651" rel="nofollow">mamadero</a><br /><strong>Subject:</strong> 1481<br /><strong>Posted:</strong> 28-Dec-2009 at 6:21pm<br /><br />Ward, <br><br>I think a bit more is needed. I'd expect DevForce to cache those logging messages and send them in batch since I don't care about the response and the timing isn't critical I can't wait and that would make it more efficient. That would also allow us to log when working offline and then resume the connection if necessary. It would also be good to have a logging configuration in the server and only send the logging messages that match that configuration (e.g. only errors, debug or info). You can see clog.codeplex.com as an example. I think this would be a nice feature as part of DevForce following the same nice programming model. <br><br>Also it would be great if I could be logging to a different server to keep our app server free for real business logic. <br><br>The other thing, I don't mind how the communication and things are resolved under the covers, but probably DevForce could help to create the LogToServer method for the client, not a big deal, just a nice to have. <br><br><br>]]>
   </description>
   <pubDate>Mon, 28 Dec 2009 18:21:25 -700</pubDate>
   <guid isPermaLink="true">http://www.ideablade.com/forum/forum_posts.asp?TID=1481&amp;PID=5997#5997</guid>
  </item> 
  <item>
   <title>Writing to Server Debug Log from Client :  I&amp;#039;ve been asked a few times...</title>
   <link>http://www.ideablade.com/forum/forum_posts.asp?TID=1481&amp;PID=5423#5423</link>
   <description>
    <![CDATA[<strong>Author:</strong> <a href="http://www.ideablade.com/forum/member_profile.asp?PF=482" rel="nofollow">WardBell</a><br /><strong>Subject:</strong> 1481<br /><strong>Posted:</strong> 18-Sep-2009 at 12:13am<br /><br />I've been asked a few times (e.g., <a href="http://www.ideablade.com/forum/forum_posts.asp?TID=1454&amp;PID=5416" target="_blank">here</a>) about how to use the DevForce Debug and Trace facilities to put client-side messages in the server-side log.<div>&nbsp;</div><div>There are lots of ways to go about it but I think one of the easiest is to use the DevForce InvokeServerMethod to pass a message to the middle tier server (our BOS) which can post the message to the server-side DebugLog on the client's behalf.</div><div>&nbsp;</div><div>You won't have to do any fancy configuration; there is no new WCF channel to configure, open, or close. You'll be using the same pipeline DevForce established for sending entities back and forth.</div><div>&nbsp;</div><div>This is actually a nifty example of using the DevForce&nbsp;ServerMethod; I hope it will inspire you to think of other uses. You should read up on it in the Developer's Guide.</div><div>&nbsp;</div><div>Before I show you the code, I want to warn you not to be too chatty in production. Every call consumes some server cycles that&nbsp;will not be available for more important needs.&nbsp;The more likely risk is that&nbsp;you blow&nbsp;up the server log with a lot of noise. You'll want to take a measured approach here.</div><div>&nbsp;</div><div>With that advisory out of the way, I proceed. </div><div>&nbsp;</div><div><strong><font size="3">ServerLogger on the Middle Tier (BOS)</font></strong></div><div>&nbsp;</div><div>Let's start with the Server where we will create a static class, ServerLogger, and give it a single static method, Log.</div><div>&nbsp;</div><div>We have to think about where to put this. It could go in its own assembly, in which case you have to remember to deploy it to the server and remember to add that assembly to the Probe Assemblies in your server configuration file (typically a web.config).</div><div>&nbsp;</div><div>I'm lazy so I'll put mine in the model assembly (called "ModelExplorer.Model" in my example) because that is sure to be deployed to the server and is already named in the Probe Assemblies of the configuration file.</div><div>&nbsp;</div><div>Our "Log" method must have the signature of a&nbsp;DevForce "IdeaBlade.EntityModel.<strong>ServerMethodDelegate</strong>". It looks like this:</div><blockquote style="margin-right: 0px;" dir="ltr"><div><font face="Courier New, Courier, mono">namespace <strong><font color="#0000ff">DomainModel </font></strong>{<br>&nbsp; public <font color="#0000ff">static </font>class ServerLogger {</font></div><div><font face="Courier New"></font>&nbsp;</div><div><font face="Courier New, Courier, mono">&nbsp;&nbsp;&nbsp; &#091;IdeaBlade.EntityModel.<strong><font color="#0000ff">AllowRpcAttribute</font></strong>&#093;<br>&nbsp;&nbsp;&nbsp; public <font color="#0000ff">static </font>object Log(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Security.Principal.<strong><font color="#0000ff">IPrincipal</font></strong> principal, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IdeaBlade.EntityModel.<font color="#0000ff">EntityManager</font> serverEntityManager, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; params <font color="#0000ff">object&#091;&#093; </font>args) {</font></div><div><font face="Courier New"></font>&nbsp;</div><div><font face="Courier New, Courier, mono">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (args.Length == 0) return null;<br></font><font face="Courier New, Courier, mono">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var msg = string.Format("Client message: '{0}'", <font color="#0000ff">args&#091;0&#093;</font>);</font></div><div><font face="Courier New"></font>&nbsp;</div><div><font face="Courier New, Courier, mono">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IdeaBlade.Core.<font color="#0000ff">TraceFns.WriteLine(msg)</font>;</font></div><div><font face="Courier New, Courier, mono">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; }<br>}</font></div></blockquote><div>I highlighted the things I want to talk about in <font color="#0000ff"><strong>blue</strong></font>.</div><div>&nbsp;</div><div>The namespace could be anything but I have to take note of it because I'll need to know it when I construct my client call.</div><div>&nbsp;</div><div>The class (and its methods) must be static. I don't like statics either but that's the way it works. </div><div>&nbsp;</div><div><strong>Be sure to keep the class stateless.</strong> That will forestall threading nightmares and help keep your server light.</div><div>&nbsp;</div><div>The log method must carry the <strong>AllowRpc</strong> attribute or DevForce won't call it. This is partly a security measure to ensure that methods which happen to have a conforming signature are not callable from the client by accident.</div><div>&nbsp;</div><div>Look at the good stuff we pass into your method. You get the <strong>Principal</strong> of the client user. Your method&nbsp;can determine by checking <font face="Courier New, Courier, mono">principal.IsInRole("xxx") </font>if this client has the right to call your method.</div><div>&nbsp;</div><div>We also give you an empty but logged-in EntityManager in case your method wants to perform some DevForce persistence operations on the server. We won't need it for our logger.</div><div>&nbsp;</div><div>Finally, there are the "args" which hold the information passed to us from the client. In our example, we expect the message to be a string&nbsp;in the first (and only) arg; we dress it up and pass it along to the DevForce TraceFns ... as if we had composed it on the server to begin with.</div><div>&nbsp;</div><div>There is not much&nbsp;type-safety here; you'll have to check that you received&nbsp;args and that they are of the expected type. It is up to you to ensure that all objects passed from the client are serializable and understood on the server.</div><div>&nbsp;</div><div>Notice that we return null. You can return any serializable object that the client understands. We have nothing to send back so we return null.</div><div>&nbsp;</div><div><strong><font size="3">Invoke the ServerLogger from the Client</font></strong></div><div>&nbsp;</div><div>In my example, I will log a message in the server DebugLog whenever I attempt a query on the client.</div><div>&nbsp;</div><div>I've jacked into the QueryRepository class in ModelExplorer.Explorer project of my Silverlight&nbsp;PrismExplorer demo where I have a collection of query "key" names and their associated LINQ queries. Just before I ask DevForce to run the query, I call the following method:</div><blockquote style="margin-right: 0px;" dir="ltr"><div><font face="Courier New, Courier, mono">LogToServer("Query called: " + queryKey;</font><font face="Courier New, Courier, mono"></font></div></blockquote><div dir="ltr"><font face="Courier New, Courier, mono"><font face="Arial, Helvetica, sans-serif" size="2">That's it. Construct the message from the&nbsp;"queryKey" and we're done!&nbsp; Ok ... here's the guts of LogToServer:</font></font></div><blockquote style="margin-right: 0px;" dir="ltr"><div><font face="Courier New, Courier, mono">private void LogToServer(string message) {<br>&nbsp;&nbsp;<br>&nbsp; <font color="#0000ff">Manager.InvokeServerMethodAsync</font>(<br>&nbsp;&nbsp;&nbsp; "<font color="#ff0000">DomainModel</font>.<font color="#0000ff">ServerLogger</font>,<font color="#ff00ff">ModelExplorer.Model</font>", <font color="#006600">// Assembly-qualified&nbsp;name for the server class</font><br>&nbsp;&nbsp;&nbsp; "Log", <font color="#006600">// name of the server method</font><br>&nbsp;&nbsp;&nbsp; delegate {}, // callback (here&nbsp;a "do nothing" delegate)<br>&nbsp;&nbsp;&nbsp; null, <font color="#006600">// state object&nbsp;to identify this particular call (we don't care)<br></font>&nbsp;&nbsp;&nbsp; message);<font color="#006600"><br></font>}</font></div></blockquote><div>The method does need access to a logged in and connected EntityManager. </div><div>&nbsp;</div><div>We are using the async form of InvokeServerMethod here. On a regular .NET client we could use the synchronous version which would block the client calling thread until the server responded. That's not allowed in Silverlight so we don't bother offering it.</div><div>&nbsp;</div><div>In practice, no matter what the client environment, you may still&nbsp;prefer the async approach for sending a message to the server; why block when you don't really care about the server response?</div><div>&nbsp;</div><div>The trickiest part of this is getting the ServerLogger class name right.</div><div>&nbsp;</div><div>I am assuming that you don't have access to the&nbsp;ServerLogger&nbsp;type on the client (generally true of server method classes) so you can't use the simpler overload in which you just supply the method delegate (e.g., <font face="Courier New, Courier, mono">ServerLogger.Log</font>). You'll have to describe the type and method with two strings.</div><div>&nbsp;</div><div>First you&nbsp;specify the class; you&nbsp;have to use the "assembly-qualified" name to identify it. That name is of the form, "<font color="#ff0000">namespace</font>.<font color="#0000ff">typename</font>,<font color="#ff00ff">assemblyname</font>", which in our example is "<font face="Courier New"><font color="#ff0000">DomainModel</font>.<font color="#0000ff">ServerLogger</font>,<font color="#ff00ff">ModelExplorer.Model</font></font>".</div><blockquote style="margin-right: 0px;" dir="ltr"><div><em>Remember from our discussion above that we slipped our server class into the same assembly that holds the domain model on the server. You wouldn't have to do it the lazy way as I have here.</em></div></blockquote><div>We must specify a callback for when the async method returns. We don't really care when it returns or what the server returns so we'll give it a "do nothing" delegate; the expression&nbsp;"<font face="Courier New">delegate {}</font>" is a quick-and-dirty way of writing a delegate that takes any parameters and does nothing.</div><div>&nbsp;</div><div>We don't care to distinguish one invocation from another so we'll give it a null "state" object.</div><div>&nbsp;</div><div>Finally, the meat: we send the message which is simply a string. This (and all arguments) passed to the server must be serializable ... which strings are.</div><div>&nbsp;</div><div>Again, no type safety here. That's why I wrapped the particulars&nbsp;in this type-safe, general purpose method which, in a real application, would be made available everywhere via a client-side "service".</div><div>&nbsp;</div><div><div><strong><font size="3">Results</font></strong></div><div>&nbsp;</div><div>After running the application and my first query, the relevant portion of the <strong>server-side</strong> DebugLog looks like this:<br><br><img src="uploads/482/DebugLog.png" height="155" width="1147" border="0" /><br></div><div>&nbsp;</div><div>I highlighted the "IdeaBladeConfig resoution so you'd know we are looking at the server-side log.</div><div>&nbsp;</div><div>I highlighted the&nbsp;entry&nbsp;for the client message&nbsp;which shows the user name of the client (this came from the Principal), the server logging method, and the message itself.</div><div>&nbsp;</div><div><div><div><strong><font size="3">Conclusion</font></strong></div></div></div><div>&nbsp;</div><div>DevForce offers an extremely simple mechanism for sending serializable material to (and from) your custom server-side method. You don't have to configure anything to use it because you're using the same client/server pipeline that DevForce employs for its own purposes.</div><div>&nbsp;</div><div>Your server method is given the client's Principal so you can impose the authorization rules you deem appropriate. You could use this same basic approach to write a server-side method that routed client traffic&nbsp;to anything your server can reach. The BOS becomes a service hub.</div><div>&nbsp;</div><div>In this example, we've put EntityManager.InvokeServerMethod to use as a simple way to pass messages from the client to the server-side log.</div></div><span style="font-size:10px"><br /><br />Edited by WardBell - 18-Sep-2009 at 12:15am</span>]]>
   </description>
   <pubDate>Fri, 18 Sep 2009 00:13:47 -700</pubDate>
   <guid isPermaLink="true">http://www.ideablade.com/forum/forum_posts.asp?TID=1481&amp;PID=5423#5423</guid>
  </item> 
 </channel>
</rss>