| William's profile.Net ZoneBlogLists | Help |
|
February 20 ReportViewer with nested tablesSometimes you may need a report that can not be done easily with standard grouping in a table. Say you want to a repeatable data region that is repeated by an outer group, but contains two other tables an maybe an image. I can't think of a good way to do that with standard row grouping using a tablix. However, the List control makes this easy. In short, here is what is needed. A List control that contains all other elements and is grouped by some value. The List gets repeated for each unique group value. Put two Tables in the List and toss in any other controls you need such as Textboxes or Images. Here is the controls layed out in Visual Studio report designer:
We get our data from the database using anything such as Linq or other. However, we "flatten" it because reports do not understand nested data. We can make developing the report simplier by skipping the DB step and making our own objects like: public class Offers { public string OfferID { get; set; } public string Offerer { get; set; } public bool IsProgram { get; set; } public string ProgramName { get; set; } public int ProgramHours { get; set; } public bool IsPrereq { get; set; } public string PrereqName { get; set; } public int PrereqCode { get; set; } public byte[] Image { get; set; } public static List<Offers> GetData() { byte[] im = File.ReadAllBytes(@"C:\Users\William\Pictures\MarkTwain.jpg"); byte[] im2 = File.ReadAllBytes(@"c:\users\william\pictures\captain_john_smith.jpg"); // Offer1 Offers of1 = new Offers(){ OfferID="03453", Offerer="John Smith", IsProgram=true, ProgramName="admission", ProgramHours=1}; of1.Image = im2; Offers of2 = new Offers(){ OfferID="03453", Offerer="John Smith", IsProgram=true, ProgramName="actual crisis", ProgramHours=10}; of2.Image = im2; Offers of3 = new Offers(){ OfferID="03453", Offerer="John Smith", IsProgram=true, ProgramName="discussion", ProgramHours=5}; of3.Image = im2; Offers of4 = new Offers(){ OfferID="03453", Offerer="John Smith", IsProgram=true, ProgramName="final notes", ProgramHours=2}; of4.Image = im2; Offers of5 = new Offers(){ OfferID="03453", Offerer="John Smith", IsPrereq=true, PrereqName="Macro econ II", PrereqCode=3463}; of5.Image = im2; Offers of6 = new Offers(){ OfferID="03453", Offerer="John Smith", IsPrereq=true, PrereqName="Finance", PrereqCode=34634}; of6.Image = im2; List<Offers> offers = new List<Offers>() {of1, of2, of3, of4, of5, of6}; // Offer2 of1 = new Offers(){ OfferID="80345", Offerer="Mark Twain", IsProgram=true, ProgramName="admission2", ProgramHours=2}; of1.Image = im; of2 = new Offers(){ OfferID="80345", Offerer="Mark Twain", IsProgram=true, ProgramName="actual crisis2", ProgramHours=3}; of2.Image = im; of3 = new Offers(){ OfferID="80345", Offerer="Mark Twain", IsProgram=true, ProgramName="discussion2", ProgramHours=4}; of3.Image = im; of4 = new Offers(){ OfferID="80345", Offerer="Mark Twain", IsProgram=true, ProgramName="final notes2", ProgramHours=7}; of4.Image = im; of5 = new Offers(){ OfferID="80345", Offerer="Mark Twain", IsPrereq=true, PrereqName="Macro econ II2", PrereqCode=3466}; of5.Image = im; of6 = new Offers(){ OfferID="80345", Offerer="Mark Twain", IsPrereq=true, PrereqName="Finance2", PrereqCode=34638}; of6.Image = im; List<Offers> offers2 = new List<Offers>(){of1, of2, of3, of4, of5, of6}; offers.AddRange(offers2); return offers; } }
Now in the Report load event of your report Form do something like: private void Offers_Load(object sender, EventArgs e) { var list = Offers.GetData(); this.OffersBindingSource.DataSource = list; this.reportViewer1.LocalReport.EnableExternalImages = true; this.reportViewer1.RefreshReport(); }
Now you have a report that has grouped "regions" and inside each region can contain other lists and/or other elements related to the group. Output: February 01 Astoria query Cheat SheetSamples Data Model:Query Samples:Below are some samples of using Astoria to query against the model. I tried to hit the most popular that will hit most of the features, but far from complete. Please let me know others you would like to see and I will keep adding. var db = SocialEntities.GetDB(); // Get the DataContext. Navigation1public void Test() { var q = from u in db.Users where u.UserID == 2 from en in u.Entries select en; //http://localhost:7777/RestService.svc/Users(2)/Entries() } Navigation2public void Test() { var q3 = (from u in db.Users where u.UserID == 2 from e in u.Entries where e.EntryID > 1 select e).Take(10); //http://localhost:7777/RestService.svc/Users(2)/Entries()?$filter=EntryID gt 1&$top=10 } String filterpublic void Test() { var q2 = from u in db.Users where u.Tag.Contains("will") || u.Tag.EndsWith("ne") select u; //http://localhost:7777/RestService.svc/Users()?$filter=substringof('will',Tag) or endswith(Tag,'ne') } Reverse Navigationpublic void Test() { var q4 = from e in db.Entries where e.EntryID == 85 // Must be 1 primary key. Range not supported. select e.Users1; // Get the user that owns this entry. // http://localhost:7777/RestService.svc/Entries(85)/Users1 } Date filterpublic void Test() { var q5 = (from u in db.Users where u.Created >= DateTime.Parse("10/1/05") && u.Created <= DateTime.Parse("11/1/09") select u).Take(5); //http://localhost:7777/RestService.svc/Users()?$filter=(Created ge datetime'2005-10-01T00:00:00') and (Created le datetime'2009-11-01T00:00:00')&$top=5 } Using Expand on Service operationThis example shows a couple concepts. It shows how one can use Expand on a service operation, and it shows how we can continue to "compose" over query. Here we use a service operation that takes 1 parameter, but we could use more or none. Linq is used to "build" the uri query, which is then executed by the .Net client stack, which is sent to the server. The servers gets the IQueryable from the method and composes over it (i.e. adds the filters and the Expand) using the client's query and returns the results. private void Test() { // Using Expand on a service operation proxy. var db = SocialEntities.GetDB(); var q3 = from u in db.GetUsers("").Expand("Entries") where u.Tag == "william" select u; Console.WriteLine(q3.ToString()); // URI: http://localhost:7777/RestService.svc/GetUsers()?$filter=Tag eq 'william'&$expand=Entries&pattern='' var user = q3.First(); Console.WriteLine("{0} {1}", user.Tag, user.Entries.Count() ); } // Client proxy method. public DataServiceQuery<Users> GetUsers(string pattern) { var q = this.CreateQuery<Users>("/GetUsers").AddQueryOption("pattern", "'" + pattern + "'"); return q; } // Service operation [WebGet] public IQueryable<Users> GetUsers(string userPattern) { if (userPattern == null || userPattern.Length == 0) return this.CurrentDataSource.Users; userPattern = userPattern.Replace('*', '%'); userPattern = userPattern.Replace('?', '_'); string filter = string.Format("it.Tag LIKE '{0}'", userPattern); var q = this.CurrentDataSource.Users.Where(filter).Select(u => u); return q; } Limit number of "Expanded" items on the many side (rSide)TMK, you can't use Expand to limit the number items on the many side. However, you can reverse the query to get the same effect. public void Test() { // Take X from many side and expand the 1 side. var q2 = (from en in db.Entries.Expand("Users") where en.Users.Tag == "william" orderby en.Created descending select en).Take(1); foreach (var en in q2) Console.WriteLine("{0} {1} {2}", en.EntryID, en.Created, en.Users.Tag); }
Return "partial" types from server using Service Operation and EFExtentions to "hide" data:Using the Entity Framework Extentions (http://code.msdn.microsoft.com/EFExtensions), you can materialize entities using all or some of the fields. Here we just return ID and Firstname from the database. One drawback here is you can not use Expand on the client side when using Materialize this way. Not sure why yet, but I assume it has something to do with the way it creates Entity Collections (or not). [WebGet] public IQueryable<Employees> GetEmployee(string empID) { // Note we create a partial employee with only selected columns, so we can return // just the data we need. The rest will be the default values of the types. string sql = string.Format("select EmployeeID, FirstName from Employees where EmployeeID='{0}'", empID); var cmd = this.CurrentDataSource.CreateStoreCommand(sql); var q = cmd.Materialize<Employees>(); return q.AsQueryable(); }
Update entity without query first:You can skip the initial query to download the object just to update it by attaching a client-side object and setting the key property. MyDataServiceContext ctx = new MyDataServiceContext(myServiceRoot); Customer cust = new Customer(); cust.ID = 1; // Set primary key for object tracking. ctx.AttachTo("Customer", cust); // Attache customer to context. cust.Name = "Bill"; // Update members of object. ctx.UpdateObject( cust ); // Set for update. ctx.SaveChanges(); January 28 Use MicrosoftReportViewer and a Dymo LabelWriter to create a really nice and 3of9 barcode labelI have to say, I had fun coding this feature. I wanted to print some 3of9 bar code labels for employee badges in a WinForms app I am rolling out. I was thinking this was going to involve some custom api and buying some font package (some are big $$). It turned out this was surprisingly simple and a fun report to build. Here is a sample label (extra points for first person to discover what is the barcode: What you need:
Steps to create the label report. I am using 3.5" x 1" labels, but same steps apply for other sizes:
Misc:
--William December 23 Tips to deploy an application (or ClickOnce) using the Griaule Fingerprint SDK 2009The Griaule fingerprint SDK is good and works well. However sometimes the documentation is lacking. After some trial and error and hair pulling I finally figured out the correct steps.
2) Add GrFinger.dll, GrFingerLicenseAgreement.txt, pthreadVC2.dll and CapPluginFingercap.dll to the project and mark them "Content" and "Copy if newer". 3) Create a new Project. Add a Reference to the .Net library GriauleFingerprintLibrary.dll to your project. This is from the 2009 sdk.
4) If using ClickOnce, make sure all the above files are "Included" as Application Files. If not using ClickOnce, the same files must be deployed with your application in the application directory.
Hope this helps someone else. I will publish a minimalist WinForm's app showing all this working with ClickOnce. Maybe even a console app. I see that DigitalPersona has a free sdk if you use there hardware. Have not tried it. If you have, please let me know how good it works. Thanks. William November 16 Return total count of query plus paging with Data Services...And in the same reply. I racked my brain for a few days trying to figure out a way to return the count of a query in the same reply with the results for my client paging control. I started with making two queries, one for the count and one for the records. There is a couple of issues with that. First, your sending two queries. Second, before you get the results of the second query, your count has probably changed. On a CRUD table, count is a point in time anyway, so you can't "count" on it being accurate. The other issue was I had to maintain two queries, one for the count and one for the results; which was difficult to maintain, so using a Batch was not really helping. It finally occured to me that I might be able to stuff the count in the HTTP reply header. As it turned out, it worked, and worked pretty well. I was able to send one query and get results and the count in same reply. Service WebGet method/// <summary> /// Returns the entries using the predicate. /// The total count of records matching the predicate is returned in /// Http header "EntryCount". /// </summary> /// <param name="predicate"></param> /// <param name="skip"></param> /// <param name="take"></param> /// <returns></returns> [WebGet] public IEnumerable<Entries> GetEntries(string predicate, string orderKeys, int skip, int take) { // TODO: Security check. if (orderKeys == null || orderKeys.Length == 0) throw new DataServiceException("orderKeys required."); // Get the records using skip and take. IEnumerable<Entries> q = null; int count = 0; if (predicate == null || predicate.Length == 0) { q = this.CurrentDataSource.Entries.OrderBy(orderKeys).Skip(skip).Take(take); count = this.CurrentDataSource.Entries.Count(); } else { q = this.CurrentDataSource.Entries.Where(predicate).OrderBy(orderKeys).Skip(skip).Take(take); count = this.CurrentDataSource.Entries.Where(predicate).Count(); } // Get the count all records matching predicate and add to HTTP header. HttpContext.Current.Response.AppendHeader("EntryCount", count.ToString()); return q; }
Client side Proxy method/// <summary> /// Get entries using a string predicate and read the total count in the reply header. /// </summary> /// <param name="predicate"></param> /// <param name="skip"></param> /// <param name="take"></param> /// <returns></returns> public IEnumerable<Entries> GetEntries(string predicate, string orderBy, int skip, int take, out int count) { // Why this work around? We have to pass an eSql string for the predicate instead of composing over IQueryable, // because at the server side we need to "know" the full predicate in order to get the count. // This also allows us to use the same query for the count and the select. if (predicate == null) predicate = ""; // Empty predicate on server side equals all rows. if (orderBy == null) throw new ArgumentNullException("orderKeys"); // order clause required. predicate = predicate.Replace("'", "''"); // Must add another single quote as these will be inside a single quote pair. string request = string.Format("GetEntries?predicate='{0}'&orderKeys='{1}'&skip={2}&take={3}", predicate, orderBy, skip, take); request = Uri.EscapeUriString(request); // Escape spaces and other. var q = this.Execute<Entries>(request.ToRelativeUri()); // Have to Execute (not CreateQuery) so we can inspect the header here. // Get full record count in header. var qReply = (QueryOperationResponse)q; // Downcast to get the Headers in the reply. Debug.WriteLine("Request URI: " + qReply.Query.RequestUri); string cs = qReply.Headers["EntryCount"]; count = int.Parse(cs); return q; }
TestOne down side here is that we have to send our query as an entity Sql string, so we don't get the help of linq expressions or designer support. If there was a way to get the user's query inside a service operation, we could use that query and append .Count() to it. TMK, there is not a way to do that with Astoria. If anyone has ideas on that, please let me know. // Get all entries > 1. Take 10 and skip 0. The count of all entries > 1 will be returned so you can set your paging buttons (i.e. Next, Prev) as needed. int count; November 13 Back to CSV - Convert CSV text to Objects; via JSONAs Json is easier to read and write then Xml. It follows that CSV (comma seperated values) is easier to read and write then Json. CSV also has tools such as Excel and others that make it easy to work with and create. So if you ever want to create a config or data file for your next app, here is some code to convert CSV to JSON to POCO objects. Control Methodpublic void ConvertCsvToObjects() { string csv = File.ReadAllText(@"c:\temp\mycsv.txt"); /* mycsv.txt - Note the doube quotes around strings are required by json. ID, Name, Price 1, "ABC", 1200.00 2, "Zip Co.", 1400 3, "Contoso", 5000 */ // Step 1: Reshape csv to a json array format. string json = csv.CsvToJson(); Console.WriteLine(json); /* JSON text [ {ID: 1, Name: "ABC", Price: 1200.00}, {ID: 2, Name: "Zip Co.", Price: 1400}, {ID: 3, Name: "Contoso", Price: 5000} ] */ // Step 2: Convert json to objects. List<Customer> customers = json.FromJson<List<Customer>>(); foreach(var cust in customers) Console.WriteLine("{0}\t{1}\t{2:c}", cust.ID, cust.Name, cust.Price); /* Output. 1 ABC $1,200.00 2 Zip Co. $1,400.00 3 Contoso $5,000.00 */ } public class Customer { public int ID {get;set;} public string Name { get; set; } public decimal Price { get; set; } } CsvToJson extention method/// <summary> /// Converts a CSV string to a Json array format. /// </summary> /// <remarks>First line in CSV must be a header with field name columns.</remarks> /// <param name="value"></param> /// <returns></returns> public static string CsvToJson(this string value) { // Get lines. if (value == null) return null; string[] lines = value.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); if (lines.Length < 2) throw new InvalidDataException("Must have header line."); // Get headers. string[] headers = lines.First().SplitQuotedLine(new char[] { ',' }, false); // Build JSON array. StringBuilder sb = new StringBuilder(); sb.AppendLine("["); for (int i = 1; i < lines.Length; i++) { string[] fields = lines[i].SplitQuotedLine(new char[] { ',', ' ' }, true, '"', false); if (fields.Length != headers.Length) throw new InvalidDataException("Field count must match header count."); var jsonElements = headers.Zip(fields, (header, field) => string.Format("{0}: {1}", header, field)).ToArray(); string jsonObject = "{" + string.Format("{0}", string.Join(",", jsonElements)) + "}"; if (i < lines.Length - 1) jsonObject += ","; sb.AppendLine(jsonObject); } sb.AppendLine("]"); return sb.ToString(); } FromJson extention methodpublic static T FromJson<T>(this string json) { JavaScriptSerializer ser = new JavaScriptSerializer(); return ser.Deserialize<T>(json); } October 27 Social RestOctober 19 LINQ-a-fi your file system and create a neat little Grep toolAfter watching this Channel9 video http://channel9.msdn.com/shows/Going+Deep/Erik-Meijer-and-Bart-De-Smet-LINQ-to-Anything/ I was inspired to try out writing my own domain specific language (DSL) for the file system. I started with writing my own Where and Select in a class, but soon discovered I did not need that. All a really needed was a method to return IEnumerable and an abstraction to make using FileSystemInfo a bit easier to use with linq. So I created LFileInfo (Linq FileInfo) for lack of a better name, and a StreamIndexer as a simple wrapper around a StreamReader to give me an Indexer (i.e. char c = file[12]) over a file. The indexer was not really required and has nothing to do with linq-ing my LFileInfo class, but it make searching the file easier in Like() algo. In effect, what we have here is another way to Grep (e.g. search) using Linq. So we created our own DSL without writing any parser code or coming up with some new syntax. We leverage the power of linq to build something fairly useful. Sample usage of LFileInfo below. Other Test methods given in the LFileInfo class: Console.WriteLine("\nGet number of files and total size under a dir."); var list = q.ToList(); // Run the query. Console.WriteLine("Total Size:{0:N} Total Files: {1}", totSize, totFiles);
// LFileInfo. Wraps a FileSystemInfo object to allow us to more simply "linq-a-fi" directory operations. namespace WJS.Utils public LFileInfo(string path) private LFileInfo(FileSystemInfo item) IEnumerable<LFileInfo> Children() IEnumerable<LFileInfo> Children(bool recurse) if (this.children != null) public string Name public string Extension public string FullName public int Level public long Length public bool IsFile public bool IsDirectory private bool CanRead public string ReadAllText() public string[] ReadAllLines() public byte[] ReadAllBytes() public bool Like(string pattern, bool caseSensitive) /// <summary> // Setup case function. // Do pattern matching. // If we have reached the end of the pattern without finding a wildcard, int cp = 0; while (j < pattern.Length && pattern[j] == '*') startIndex = i; /// <summary> // Convert both string and pattern to lower case for comparison. // If pattern doesn't actually contain any wildcards, use simple equality. // Otherwise do pattern matching. // If we have reached the end of the pattern without finding a wildcard, int cp = 0; while (j < pattern.Length && pattern[j] == '*') return j >= pattern.Length; // Some sample tests. Remove Test methods from final code. public static void Test2() foreach(var f in q) public static void Test3() foreach (var f in q) Console.WriteLine("Total Size:{0:N} Total Files: {1}", totSize, totFiles); // Print a dir tree to the console. LFileInfo dir = new LFileInfo(path); // Use Like pattern matching to search files. var list = q.ToList(); /// <summary> if (entry.IsDirectory)
// StreamIndexer class to wrap a StreamReader and expose an indexer. namespace WJS.Utils public long Length public void Close() public IEnumerable<Char> Characters() public int this[int index] October 09 Fiddler with Ado.Net Data ServicesTo get Fiddler 2.1.8.2 to work with Visual Studio Development server and using Ado.Net Rest services, I found only 1 thing that actually works: 1) Add a new host to your \etc\hosts file: 127.0.0.1 local The name is not important, but local works. localhost does not work for some reason with Fiddler. 2) Set Fiddler to filter on host name "local". Just to filter out public traffic on your machine. 3) Change your client library URL to use the new URL. If you have Application settings in the client project, change the ServiceUri. If you use Client Application services, also change those locations in the application Properties / Services tab. Use your service name below. Example: http://local:7777/RestService.svc/ 4) Change your Rest service's web.config to listen on "local" name. Use Specific Port instead of Auto-assign port in Web tab of application Properties. <services> 5) Verify service starts and listens on URL from a brower and point to http://local:7777/RestService.svc/ to see the service meta data. Other solutions on the net such as adding a dot to localhost http://localhost.:7777/Service.svc/ Do not seem to work for me (at least on Vista). The solution above works from .Net client app and IE. September 13 OpenID and CardSpaceOpenID and CardSpace are both complementary and competing technologies. An interesting thing about OpenID it that it allows you to "attach" a Card to your OpenID account (create an openid at myopenid.com if you have not already). That is interesting as it allows you to logon to your OpenID account using your InfoCard on your desktop. That is pretty powerful because that means you can logon to any OpenID site using your InfoCard. So the web designer that enables OpenID logins will also get CardSpace for free without writing a single line of additional code - that is pretty cool. In a previous post, I wrote on the need of a Proxy that would allow me to get my Card easily when on a public pc. OpenID with cardspace support does not get us there, because I still have to have the card on the machine I am at in order to authenticate to OpenID using my card. However, OpenID does allow me to login using name/pwd pair, so that is always a good last resort. However this can be made better I think. What if the OpenID provider also "stored" my Card in encrypted form? Then I could download that card and use it. To make this process simple, MS needs to create a temp proxy card. So on a new machine I create a TProxy card that have my name and a URI to my OpenID provider. Now when I try to use TProxy card, it downloads my real card from the provider and decrypts by prompting for a password. Now that I have my real card local, I can then continue to use as normal during the session. The provider only ever sees my card in encrypted form so it is protected from snooping. Now the question is how to get rid of local card when done? If I log out, the CardSpace framework and just clear card memory and be done. But what if I just walk away and forget to logout? I guess that is same issue as forgetting your credit card at a store and hoping nobody uses it until you cancel the card. One option to mitigate the risk is to add a timeout on the card. I guess another option would be a usb smart card and a pwd pair. Keep your smart card on your key chain and you can login anywhere. Loose your card, and someone still needs your password. So I need to login once (to decrypt the card on the smart card) and can use the card for remainder of my session. September 12 CardSpace (InfoCard) replay and thoughtsInfoCard (i.e. CardSpace) has been out for a bit, but does not get much joy yet. I think probably cause a lot people just don't know about it or don't care yet. But the other day I created a OpenID and started using it for identi.ca. identi.ca is a good example of a site that uses OpenID well and makes it easy. That got me thinking all sites should use OpenID. Then I rediscovered CardSpace because OpenID also always you to attach an InfoCard to your id. So that got me thinking more about CardSpace and using it for my web site. In general, I am starting to think InfoCard (or the idea of InfoCard) is almost the perfect security model for the following reasons: 1) You control your cards locally. You don't have various names and password strung out all over the INET. 2) You can use same card on multiple sites. 3) You only share the info you want in the card. 4) You get to pick your card at login using a picture and named card. This makes it easy to remember what card you used at what site. Vista actually has a nice CardSpace control for this and it works well (can download for XP). 5) People can't hack your password on a site using normal hash tables (rainbow) or brute force. I am not sure yet if it is possible to brute force an InfoCard. 6) It moves the security model to a standard and tested model. Today, each site may (or may not) protect your password with all kinds of good or no good hash and/or encryption methods. Point it, you don't know what method is used - it could be stored in the clear! InfoCard removes many of the server side variants and acts almost like an agent on your behalf. 7) The framework it there where in the future you can time limit your card and revoke it from use. Given the upsides and the fact that I am in control of the card, I am starting to wonder if OpenID is the right model. That said, AFAICT, there is one primary down side - you have to have your card on each machine you use. That means if you are on some random machine, you need to figure our how to get your card and have to worry about removing it from the machine when you done. Maybe what we need is password protected Temp Proxy Card. When you are at a "public" PC, you create a Proxy Card that includes the URL of your real card (stored at a public URL that is encrypted AES with your known password). Then browse to web site that requires a card, the Card selector will popup and you select your Proxy card. The framework will download and decrypt your real card and use that and cache it in memory only in encrypted form using your same password as your proxy card. Maybe it also has a time limit on it. Make your web site InfoCard enabled. I have looked at a couple solutions, but found Dominick's control the best fit and ease of use. It also supports non-SSL mode, as many web sites (i.e. blogs) do not use SSL. Having the option is nice. Dominick Baier's IC Selector at: http://www.codeplex.com/InfoCardSelector/Release/ProjectReleases.aspx?ReleaseId=12626 August 23 Transaction is not allowed error using ADO.Net Entities.Doing some ADO.Net Entity queries and updates the other day, I kept getting this exception: "New transaction is not allowed because there are other threads running in the session."
The reason is we have an open Reader in our foreach and we can't nest trasactions like that. The solution is to read everything we need first so we close the reader. The simple solution here is to append .ToArray() like:
August 20 ADO.Net Data Services after Silverlight Tools sp1After installing Silverlight VS Tools SP1 beta, not only did SL designer not work, but it somehow messed up my ADO.Net REST services. Was getting strange exceptions. I uninstalled SL Tools and reinstalled VS SP1 (not sure if that was needed) and ADO.Net data services seem to be back working again. Short story, don't install SL tools yet. I should say, don't install beta software - but I could not follow my own advice. Silverlight Streaming ServiceIf you have not looked at in a while, the new SL service allows you to directly upload you .wmv files. So you don't need to use Encoder anymore to encode a SL video into a SL application. This makes it really simple to public videos for your blogs, etc. After uploading your video, the service gives you chance to do a quick preview and gives you the html you need to embed the video in your blog. Simple and elegant - nice. August 14 Microsoft Response Point PBXMan, I am really excited about the new small business PBX system MS released - Response Point. It seems like one of those no brainers - Create a platform that can be extended and programmed against easily using .Net, have a blue button and voice commands, connect the phone via Ethernet and IP, and make it super easy to hookup,manage, and buy. That is a formula for success IMO. I am looking forward to seeing the SDK. I can already envision a wave of social apps for this thing. Now I just need to figure out how to get one to experiment with... January 09 Enterprise Framework LINQ Queries failing - MSDN ForumsGood Linq post from Colin Meek below:
January 06 Make existing project a Volta project - MSDN Forums
|
|
|