text:
Exploring language
Longman, 1998 - Education - 582 pages
From the Publisher: Exploring Language features thought-provoking readings that explore the various interconnections between language and American society. The text challenges the reader to critically examine how language affects and constructs culture and how culture constructs and affects language. Key topics include Gender and Language; Hate Speech; Language of War; Censorship.
From inside the book
22 pages matching girls in this book
Where's the rest of this book?
Results 1-3 of 22
What people are saying - Write a review
Review: Exploring LanguageUser Review - Bernie - Goodreads
A very good book to explore for someone interested in writing. Read full review
Review: Exploring LanguageUser Review - Richard - Goodreads
Read some of the short essays for my English 101 class. As a college text nothing much to say for or against it. We did have some interesting discussions in class using the essays in this book as a jumping off point.. Read full review
Related books
A Brief History of English
Homemade Education
70 other sections not shown
Other editions - View all
Common terms and phrases
References to this book
References from web pages
Pearson - Exploring Language, 9/E
Celebrating its 25th anniversary, Exploring Language remains the market-leading language reader. Despite this thorough revision of the 9th edition, ...
www.pearsonhighered.com/ academic/ product/ 0,,0321055187,00%2Ben-USS_01DBC.html
Linguistics - Introduction to Linguistics - Exploring Language ...
Linguistics,Introduction to Linguistics,Exploring Language,Gary Goshgarian,9780321122216,978-0-3211-2221-6,0-32112-221-6,0321122216,Mehr als 70.000 ...
www.pearson.ch/ HigherEducation/ Linguistics/ IntroductiontoLinguistics/ 1471/ 9780321122216/ Exploring-Language.aspx
Writing Textbooks
Nevertheless, Goshgarian writes that "the original character and objective of Exploring Language remains the same: to bring together exciting and readable ...
www.case.edu/ artsci/ engl/ emmons/ writing/ textbooks/ explang.html
�What Students Have Taught Me About Writing,� essay in Exploring Language, 10th edition/20th anniversary issue, Ed. Gary Goshgarian, Pearson/Longman, 2003. ...
www.mccallie.org/ pchilder/ PUBLICATIONS.doc
Exploring Language
Welcome to the Companion Website to accompany Exploring Language, 10th edition, by Gary Goshgarian. Students can find material to enrich their learning ...
wps.ablongman.com/ long_goshgarian_el_10/ 12/ 3121/ 799197.cw/ main/ index.html
JSTOR: Readings in the Theory of Grammar
Exploring Language should be immedi- ately differentiated from the other books ... As the content survey suggests, Exploring Language offers wide-ranging ...
links.jstor.org/ sici?sici=0010-096X(197802)29%3A1%3C95%3ARITTOG%3E2.0.CO%3B2-Y
Barnes & Noble.com - Books: Exploring Language, by Gary Goshgarian ...
Exploring Language, Goshgarian, Gary Goshgarian, Paperback, 11TH, 11, Book, ISBN: 0321457978, Anthropology & Archaeology, Writing, General Reference, ...
search.barnesandnoble.com/ Exploring-Language/ Gary-Goshgarian/ e/ 9780321457974
New Media and the New Research
Reading Life ands Exploring Language but could not find any promising ones in Writing. About the World. Ullman, Ellen. �The Museum of Me. ...
www.uoregon.edu/ ~csoles1/ pdfs/ New%20Media%20and%20the%20New%20Research.pdf
Language and Politics: Indirectness in Political Discourse ...
Exploring Language. Glenview, IL: Scott, Foreman and Co. Blum-Kulka, S. (1983) `The Dynamics of Political Interviews', Text32: 131-155. ...
das.sagepub.com/ cgi/ content/ refs/ 8/ 1/ 49
Writers, Readers, Researchers: Beware! Propaganda Ahead! Barbara ...
Exploring Language. Ed. Gary Goshgarian. Toronto: Little, Brown & Company, 1986. ... Exploring Language. Toronto: Little,Brown & Company, 1986. ...
www.mala.bc.ca/ ~soules/ eng315/ textbook/ douglas.htm


text:
Liberty Theatre
136 S. Main Street,
Los Angeles,
3 people favorited this theater
The Novelty Theatre was listed in the 1926 edition of Film Daily Yearbook with 350 seats. It was located at 136 S. Main Street.
Recent comments (view all 22 comments)
"The Feud of the Trail" is dated 1937, so a 1938 date sounds reasonable.
I found a 1905 ad for the Novelty Theater at 523 S. Main. I posted a comment on the Gaiety page.
The LA Times noted in 1948 that Mexican films were being shown at the Liberty, California and Mason theaters.
Here is another photo, probably around the same time as the first one I posted:
What kind of films was the Liberty showing in April 1942? Not Disney, apparently. The ad is from the LA Times:
Based on all the evidence provided above, it looks like the 136 S. Main location was not The Liberty until around 1942, when it was showing porno, or whatever the 1940's equivalent to porno was.
Who knows how long it lasted after that? As late as 1938 it was oeprating as the Novelty, showing 5 movies plus a serial for a nickel.
It seems like the 262 S. Main location was the Liberty much earlier, around 1910, lasting until..??? This was the theater with the elegant arch shown in the postcard.
Wish I could have gone to the Novelty, with its cheap-ass appearance and program of cheesy B-westerns. Looks like it was a lot of fun. Before my time. Even my Dad was only 7 years old at this time.
In 1942 the Chinese was at 136 S. Main, according to the city directory of that year.
The same directory also lists the Novelty at 136 S. Main in 1942.
Looks like the address above is correct.
All new buildings up and down the block now.
Just login to your account and subscribe to this theater

subset: commoncrawl


text:
Godolphin - National Trust
Godolphin - National Trust
Godolphin Cross
General Enquiries
+44 (0) 1736 763 194
General Enquiries
+44 (0) 1736 763 194
A historic house and medieval garden all set within an ancient and atmospheric estate
Discover Godolphin, one of the most fashionable houses in Cornwall in the 17th century. Long since abandoned, you can soak up the atmosphere of peace and antiquity as you explore this romantic home.
Wander around the 16th century garden, one of the most important historic gardens in Europe. It has barely changed over the years.
Venue Type:
Garden, parklands or rural site, Historic house or home
Easter - End of September:
May, June and Sept - Thurs and Fri 11.00-17.00
July and August - Tues, Thurs and Fri 11.00-17.00
Every Sun - 14.00-17.00
Every Bank Holiday Mon - 11.00-17.00
Adults: £5.00
Children: £1.50
Seed Sowing
- 5 August 2014 11am-3pm
- 21 August 2014 11am-3pm
The Godolphin gardeners invite you to the ancient garden to learn about seed sowing. Why not have a go yourself? Learn about the different varieties, and sow some seeds to take home and grow.
Suitable for
- Any age
Normal Admission Charges Apply.
Save Our Native Bluebell!
- 11 May 2014 11am-12:30pm
Join Godolphin's gardener for a walk and talk around the garden. Learn about the current threat to the native bluebell from the Spanish varieties, and walk through the sea of blue in Godolphin's far orchard.
Suitable for
- Any age
June Jaunt
- 18 June 2014 11am-3pm
There's nothing quite like a countryside jaunt on a warm day in June. Join Godolphin's Ranger on a guided walk around the estate, learn about the flora and fauna, as well as the rich local mining history. We invite you to bring a picnic, as you'll find a great spot to stop and take in the scenery. If you'd like, why not buy a sandwich or some homemade cake from our tea-room, to take with you.
Suitable for
- Any age
Booking Essential 01736 763194.
Barefoot Hike at Godolphin
- 26 July 2014 10am-1pm
An easy stroll up Godolphin Hill for beginners and children. Enjoy the barefoot-friendly textures as we very gently climb to one of the most spectacular views in West Cornwall. Free but donations welcome.
Suitable for
- Any age
Booking Essential 01736 761013.
Nature Night Walk
- 15 August 2014 8:30-10:30pm
As the light begins to fade, meet us at the Piggery where we'll begin our guided Nature Night Walk. Through exploring the garden and estate you'll discover Godolphin's nocturnal residents including rare breeds of bats and owls, and experience the atmosphere of this historic place. Remember to pack your torch!
Suitable for
- Any age
Booking Essential 01736 763194. Adult £4.00, Child £2.00.
- About
- | Collections
- | Events
- | Map


text:
Types of Vehicle Registration Transactions
When completing a Vermont Registration Application ( 424.7KB) you must indicate what type of transaction you need to register your vehicle --- a New Registration, a Transfer or a Renewal. The following is a brief explanation of the meaning of the three types of transactions:
NEW REGISTRATION (1st time Vermont registration):
- New plates are issued.
- May be a vehicle purchased in Vermont or out of state (in this situation you must complete the entire Vermont Registration Application ( 424.7KB) ---a Visual Verification Of Serial Number may be required).
- Registration plates are assigned and mailed to you unless you indicate otherwise (such as Vanity plates).
TRANSFER OF REGISTRATION (For transfer of your Vermont registration from one vehicle to another:
- Complete the entire Vermont Registration Application ( 424.7KB).
- In "Section #1A" of the form enter the Plate number that you are transferring.
- You must send in your current Vermont Registration with the "Transfer Section" completed, or fill out "Section #6" of the Vermont Registration Application you are completing.
- A change of legal ownership of the vehicle you are transferring from must occur before a transfer of registration will be allowed.
RENEWAL OF REGISTRATION (This is for renewal of your Vermont registration only):
- Normally you will receive a computer-printed renewal application in the mail. If you do not receive the computer-printed application it will be necessary for you to complete a Vermont Registration Application ( 424.7KB) and your renewal must be delivered to our main office in Montpelier (it cannot be processed at any of our satellite offices).
- When completing the Vermont Registration Application complete Sections 1 (and 1a and 1c if applicable), 2, 4 and 8
- Complete sections 3A-3D if renewing one of the following: Tractor, Truck (including pick-up truck), Agriculture Vehicle, Trailer, Motorcycle, Motor-Driven Cycle, Motorbus, Jitney or Rental Vehicle.
- In "Section #1A" of the form enter the plate number you are renewing.


text:
It's Hatched!
DealChicken's got a job to do, so he's not going to let the cold and wind stop him from finding great deals - like this one on a winter sport mask. The winter sport mask can keep your face warm and protect your ears and nose from the cold, whether you're revving up the snowmobile, lacing up the ice skates for winter fun or strapping on the snowboard for some downhill action. The mask comfortably fits under helmets, so you won't have to sacrifice warmth for safety.
$9.95 for an ergonomic winter sports mask ($30 value)
Widget Love
Calling All Shoppers...
Calling All Merchants...
Stay Connected!
© 2010-2014
DealChicken.com. All Rights Reserved. Users of this site agree to the
Terms of Service
Privacy Policy / Your California Privacy Rights
Ad Choices
Subscribe below and we'll send you a daily deal alert for St. Louis.
MontgomeryPhoenixPhoenix - East Valley Phoenix - West ValleyScottsdale/Paradise ValleyTucsonLittle RockMountain HomePalm SpringsSacramentoSalinasVisaliaDenverNorthern ColoradoDelawareWashingtonFort Myers/Cape CoralFSUJacksonvillePensacolaSpace CoastTallahasseeTampa BayUCF / East Seminole CountyAtlantaAtlanta NorthAtlanta SouthMaconGuamChicagoEast Central Indiana / RichmondIndianapolisLafayetteMuncieDes MoinesIowa CityLouisvilleAcadianaCentral LouisianaMonroe/West MonroeOpelousasShreveportBangorPortlandMontgomery CountySalisbury/Ocean CityBattle Creek / KalamazooDetroitGrand RapidsLansingLivingston CountyPort HuronCentral MinnesotaTwin CitiesHattiesburgJacksonOzarksSt. LouisGreat FallsRenoCentral JerseyCumberland CountyMonmouth CountyNorth JerseyOcean CountySouth JerseyBinghamtonBuffaloElmiraIthacaPoughkeepsieRochesterRockland-GreaterWestchesterWestchester-Shore TownsAshevilleThe TriadCincinnatiClevelandCoshocton / Holmes CountyFairfield CountyGreater CincinnatiLicking CountyMarion CountyMuskingum ValleyNorth Central OhioNorth CoastScioto ValleySalemBucks/MontgomeryPittsburghColumbiaGreenvilleSioux FallsClarksvilleJacksonKnoxvilleMurfreesboroNashvilleSouthern UtahNorthern VermontNorthern VirginiaStauntonCentral WisconsinFond du Lac / OshkoshFox CitiesGreen BaySheboygan / Manitowoc
There's one last thing we need from you to create your account.


text:
The Clark is "Club Tokyo" February 3 During the Next Event in the Popular "Clark After Dark" Series
For Immediate Release
January 13, 2006
The Sterling and Francine Clark Art Institute's wildly-popular "Clark After Dark" quartet of winter revelries takes guests far from the New England winter and spring thaw. Each party is different, with theme-based food, signature drinks, movies, games, and activities. On Friday, February 3 from 8 pm to midnight, the Clark will morph into a club on the other side of the world. Dress to impress, whether it's a kimono or club clothes, and enter Tokyo pop-culture where partygoers can eat sushi, practice origami, and rock the house with karaoke. Tickets are $10 ($8 for members) per evening and are available at the door, or by reservation at 413-458-0524 or email@example.com.
Japanese influences are everywhere during this event, from the fabulous food and artistic activities, to the projection of anime films in the courtyard. Learn the ancient art of origami with hands-on folding. Those curious about the martial arts won't want to miss demonstrations by Bob and Lisken Dus.
The Academy Award winning film Lost in Translation will play on the Clark's big screen at 9 pm. Directed by Sofia Coppola, this 1993 film stars Bill Murray, as a movie star past his prime, and Scarlett Johansson, a neglected newlywed, who meet as strangers in Tokyo and form an unlikely bond.
Karaoke, a time-honored party tradition, will make stars out of the brave souls who dare to sing their hearts out competing for prizes. Those who would rather dance than sing will groove on the dance floor to a DJ spinning techno tunes.
"Club Tokyo" wouldn't be complete without sushi and "saketinis" for purchase, and a full cash bar. Additional snacks and soft drinks will be provided.
A highlight of the evening will be a rare after-dark peek of the Clark's print room. On view will be rarely-seen Japanese prints hand-picked for the evening. With an impressive holding of over 5,000 works on paper, the Clark's collection of prints, drawings, and photographs includes masterpieces by Picasso, Cézanne, Degas, Bonnard, Stieglitz, Rembrandt, Lartigue, Whistler, and many other great artists.
Continuing the "after hours" gallery viewing made popular at this summer's 50 Hours weekend, the Clark's galleries will be open until midnight offering late-night rendezvous with masterpieces.
The Clark After Dark carousing continues with "Venetian Carnivale" on March 3 and the "Last Days of Pompeii" on April 7.
The Clark is located at 225 South Street in Williamstown, Massachusetts. The galleries are open Tuesday through Sunday from 10 am to 5 pm (daily in July and August). Admission is free November through May. Admission June 1 through October 31 is $10 for adults, free for children 18 and younger, members, and students with valid ID. For more information, call 413-458-2303 or visit www.clarkart.edu.


text:
Microsoft Products for Students
Welcome to the ECU Microsoft Office for Students Distribution Center. All enrolled students are eligible for FREE Microsoft products!
To begin, enter your PirateID and passphrase below to log in to the Microsoft Kivuto Solutions Web store.* Instantly download and install your choice of these applications:
Microsoft Office 2010, 2013, 2011 (Mac) | Windows 7 or Windows 8
This is a full license and yours to keep, even after graduation.
Students are encouraged to burn their software to DVD for safekeeping or reinstallation. DVD media can also be ordered during initial download (student pays shipping).
Orders are accessible (available for download) for 31 days past the original order date. Students can also pay a $4.95 Extended Access Guarantee to keep the order open for 24 months.
NOTE: Orders older than 31 days are archived. To re-open an archived order for another 60 days is an $11.95 charge to the student.
*By clicking the Submit button, you are leaving the East Carolina University website and being redirected to the Microsoft Kivuto Solutions website. ECU has no responsibility for any external website.
Program Description
Eligible students are allowed one license from the latest version of each application below.
Microsoft Windows Operating system
Perpetual license; you must be a licensed user of one of the following products to be eligible for installation of Microsoft Windows (Operating System) Professional Upgrade License.
Microsoft Windows 7 (32/64-bit) Professional | Professional Upgrade (English) | Ultimate | Ultimate Upgrade 32/64-bit (English)
Microsoft windows 8 (32/64-bit) Professional | Professional Upgrade (multilanguage) | Mac Professional Upgrade 32/64-bit (English)*
*Mac users only. Intended to be used in conjunction with third-party virtualization software.
Office Professional 2007, 2010, 2013
(32/64-bit). Perpetual license; includes the following applications:
Office 2010 (Professional Plus): Access | Excel | InfoPath | Lync | OneNote | Outlook w/Business Contact Mgr | PowerPoint | Publisher | SharePoint Workspace | Word
Office 2013 (Professional Plus): Access | Excel | InfoPath | Lync | OneNote | Outlook w/Business Contact Mgr | PowerPoint | Publisher | OneDrive | Word
Microsoft Office 2011 for Mac
Perpetual license; includes the following applications:
Excel | Outlook | PowerPoint | Word | Communicator


text:
This blog has personalition features for you, the reader. Below is a key of what all the icons mean and which aspects of the layout they change.
Close Window
This post is about scrolling in WPF and the egocentric DataGrid control. I'll give the project background but if all you're interested in is the final solution, scroll on down a bit. I'll leave a trail of headers so you should be able to find your way easily enough.
I've been working on a little application to help track spells for my wife's character in our weekly Pathfinder games (my character might find a use for it as well but that's just gravy). Since I had already spent a couple months dinking around with acquiring (and normalizing into XML) the reference version of the spells, I figured all I really needed was a UI to present and track them. I mean, I have a strong object graph and a library of spells, UI is really all that's left, right?
For the UI, I decided to lean on WPF—mostly so I could come to understand the many data binding techniques I'd learned at TechEd this year. Plus, I had some ideas of how I wanted to leverage a composite UI for the presentation. This turns out to have been an awesome idea and allowed me to do exactly what I wanted, though it sometimes took a while to figure out how to do the cool stuff.
As part of the project, I also wanted to get some experience with actually using MVVM in a live project and set myself the task of using as little code-behind as possible.
As I said above, things went well. I had to learn my way around a few problems, but things mostly worked the way I thought they should and while the end result would be cleaner if I'd started out knowing what I know now, I'm pretty proud of the results. I got the UI to alter dynamically depending on whether the character class had Domains. Or bloodlines. Or neither. I had some fun building in filtering capabilities. And you can even choose the sources you accept into your spell list.
The one thing that had me tearing my hair out, in the end, was that the list of spells didn't scroll right. Since the spells need to be divided by level, I have a ListView with a custom data template. Each item in the ListView is a whole level's worth of spells. The custom data template has a WrapPanel for the level header information (spells per day, spell DC—things that vary by level) and then a DataGrid for the spall data itself. Here's a screenshot if you're curious:
For mouse wheel scrolling, if the mouse was on the level header (the yellow bit), or if you scroll all the way to the right where the DataGrid ceases to rule, it'd scroll just fine. Actually, that's a lie. It'd scroll just fine once you turned off ScrollViewer.CanScroll on the ListView (if you don't, then the ListView scrolls it in chunks, a level/item at a time).
This got very annoying because as far as I'm concerned, if there's a scroll bar, the mouse wheel should move it. And since the list tends to be long, I was forever trying to scroll with my wheel.
By poking at it repeatedly with a debugger and wiring up random events, I came to understand that the DataGrid was eating my MouseWheel event. And since that's the bottom control on the event route (WPF starts the event routing at the bottom of the tree), the MouseWheel wasn't being seen by itself (the DataGrid), its parent (the StackPanel), or its parent's parent (the ListView). My guess is that DataGrids expect to be the king of scrolling and figure they own the MouseWheel events because you, the developer, will only screw it up if they let you.
So I went digging to see if there wasn't something I could do to wrest MouseWheel events from the DataGrid. It was clear that I'd need to do something to manually handle mouse events and, also manually, dictate scrolling behavior during same. The only control I could find that exposed the right methods is the ScrollViewer control as explained in this Stack Overflow answer. That's exactly what I need, but to use it, I'd need to insert a ScrollViewer into the control hierarchy. And the only place to do that, such that it'd actually work the way you'd expect, is to insert it into the ListView somehow. This turned out to be trickier than it looks.
My initial impulse was to replace the ItemsPanel on the ListView. Unfortunately, the ItemsPanel has to be just that—a panel. ScrollViewer isn't a panel and any panel you insert there is going to have the same problem as the ListView itself. It took me a while to work out how to do it (because the documentation for template-type properties is long on detail and short on information), but I finally figured out that overriding the ControlTemplate was the way to go. A little back and forth and I came out with this simple-after-the-fact solution.
<ListView Margin="8,155,8,8" ItemsSource="{Binding Source={StaticResource characterViewModelClassesViewSource}, Path=SpellLevels, UpdateSourceTrigger=PropertyChanged}" ItemTemplate="{DynamicResource spellLevelDataTemplate}" ScrollViewer.CanContentScroll="False" IsTextSearchEnabled="False" Name="spellsListView"> <ListView.Template> <ControlTemplate> <ScrollViewer PreviewMouseWheel="ScrollViewer_PreviewMouseWheel"> <StackPanel IsItemsHost="True"/> </ScrollViewer> </ControlTemplate> </ListView.Template> </ListView>
With the ScrollViewer in place, the event itself was simple, too.
private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { ScrollViewer scv = (ScrollViewer)sender; scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta); e.Handled = true; }
If you actually followed the Stack Overflow link, you'll recognize that I lifted the code pretty much wholesale.
So now, my ListView eats the MouseWheel event (via PreviewMouseWheel), but only after it actually moves the scroll bar correctly.
author: Jacob | posted @ Monday, July 18, 2011 6:07 PM | Feedback (0)
While I prefer working through GP Web Services, sometimes the functionality you want/need simply isn't there. Many people drop from Web Services directly to table access, but I prefer seeing if I can't get what I need through eConnect instead. Generally speaking, I can.
Unfortunately, the eConnect SDK documentation is sparse and only really useful for simple cases. Raw schema files and cryptic explanations are par for the course and this can be frustrating.
So, I'm working on an application that requires that I take a Universal Locator Id and walk that back to the customer I need to ship something to. For reasons buried in the depths of time, the UL is stored on the COMMENT2 field of the Customer Card. Since GP Web Services doesn't expose COMMENT2 in its search criteria, I dropped back to eConnect.
Simple right? I mean, the request document has a "WhereClause" element for just that purpose so how hard can it be? Here's the documentation:
Allows users to pass in a custom "where clause" built from columns of the parent table of the requested document type.
So I cranked up my eConnect library project and came up with the following code:
private RQeConnectOutType getRequest(string CustomerUL){ eConnectOut outDoc = new eConnectOut() { DOCTYPE = "Customer", OUTPUTTYPE = 1, INDEX1FROM = "A001", INDEX1TO = "Z001", WhereClause = string.Format("COMMENT2 = '{0}'", CustomerUL) }; RQeConnectOutType outType = new RQeConnectOutType() { eConnectOut = outDoc }; return outType;}
The only problem is, this returns every customer record. All the time. And it does so for every alternative expression I could think of. Questioning my assumptions on this to get it to work was an exercise in futility.
And no amount of search-fu helped me find a satisfactory answer to getting this to work. As far as the internet is concerned, everybody who tries this either gives up or doesn't have to be told how to get it working.
Well, I eventually got it to work, and I thought I'd share so the next schmuck who goes through this doesn't have to suffer through the despair I did to get there (at least, not if their search engine of choice can point him here).
The key to this working is to tell eConnect that you don't want to work from the "shadow" tables. What's a shadow table, you ask? Well, I can't be certain, but I think that it refers to the e_Connect_Out table stuck in your database by eConnect. This table has summary records that you might want to work with in eConnect, with details on where to get the full record. I can't tell you for certain because the SDK documentation doesn't actually have a section explaining shadow tables.
The problem is that when working with the shadow tables, things that aren't in an index field aren't really available for filtering purposes. Thus, my WhereClause referring to COMMENT2 doesn't do a thing because the shadow table doesn't know from COMMENT2. The fix for this is to use the woefully misnamed element "FORLIST". Here's what the documentation says:
0=Return items from the shadow table. Use ACTION to specify the type of returned data.
1=Returns a list of items directly from the actual tables; does not use shadow tables
Well, hoodyhoo! That's exactly what I needed (though I didn't know it until I tried it). So here's the code that actually works:
private RQeConnectOutType getRequest(string CustomerUL){ eConnectOut outDoc = new eConnectOut() { DOCTYPE = "Customer", OUTPUTTYPE = 1, FORLIST = 1, INDEX1FROM = "A001", INDEX1TO = "Z001", WhereClause = string.Format("COMMENT2 = '{0}'", CustomerUL) }; RQeConnectOutType outType = new RQeConnectOutType() { eConnectOut = outDoc }; return outType;}
I've bolded the only change. Not only does this work, but it works fast. So now you know. If you want your filter to work in the WhereClause and it just won't take, try pointing it at the real tables. I know that "FORLIST" is the obvious place to do this, but I thought I'd point it out, anyway (in case I forget).
author: Jacob | posted @ Thursday, August 19, 2010 6:05 PM | Feedback (3)
As you may have figured out from past posts, I like working with Dynamics GP Web Services when building integrations that involve our business systems. That isn't to say that there aren't rough spots occasionally. My latest wrestling match with it involved updating Sales Invoices. Since I couldn't find information on this issue at all, I thought I'd post my struggle and solution for others in the same situation in future to find.
We have multiple bins configured on our sales invoices so that we can coordinate our warehouse folks and get orders shipped quickly. That means that for each line on the invoice, inventory can come from one or more bins (if needed) to fulfill the order. Since GP isn't very flexible in its automatic bin assignment, we have an addin that we run to allocate bins. I programmed the addin.
Sending a sales document through GP Web Services with multiple bins attached to each line item was impossible to do on Sales Orders because of a bug in the update procs that I found a couple months ago (where the bins simply aren't updated). As a result, we have to wait until an invoice is created for the document to be able to assign bins through the web services. A pain, but not a huge deal, really.
Dynamics version: 10.00.1368
SQL Server version: 2005
Visual Studio: 2010 (10.0.30319.1)
Target Framework: .Net Framework 3.5
Transport: WCF using basicHttpBinding
The thing is, I was having trouble making my bin allocation re-entrant. It could be that you might want to run bin allocation twice on a batch of invoices if, say, you had shortages in the available bins on one or two orders but were able to move things around a bit to make it work. It seems reasonable. Then, too, we found that another process that was updating shipping dates on invoice batches was causing problems, as well.
A little experimentation showed that updating an invoice through the web services that already had multiple bins allocated caused Dynamics GP to lose track of the allocations entirely. Fortunately, it did so in such a way that the inventory wasn't messed up—i.e. it reverted back to the bins they had come from. Unfortunately, I could find no way to allow my bin allocations to be re-entrant and/or for my batch date change application to touch my Sales Invoices without bad things happening.
I found that even if you sent an absolutely unaltered invoice back to GP in a web services update operation, it'd lose bin allocations if they existed—whether your update included those bin allocations or not.
I finally got a wacky idea that turns out to work a dream. It's less than ideal, but hey, it works without having to drop down to eConnect or anything even less friendly. The trick is to fake Dynamics out with a superfluous update if you have an order with bins already allocated. Here's the code:
public List<CustValidationItem> CommitSalesInvoice(){ OnCommitting(); GPService.SalesInvoice si = originalSalesDocument as GPService.SalesInvoice; if (si == null) { si = new GPService.SalesInvoice(); } else { int allocatedCount = si.Lines.Count(l => l.QuantityFulfilled.Value > 0M); if (allocatedCount == si.Lines.Count()) { fakeoutUpdate(si); } }
In this code, originalSalesDocument is completely untouched and exactly the invoice as read from the web service earlier. If you were to break after fakeoutUpdate() is called, the invoice would have no bins allocated for any of the line items.
Note that I have a potential bug in there if an invoice is ever partially allocated (because then allocatedCount would be less than the total number of lines), but I'm considering that a feature for now (because it will de-allocate all bin allocations on that invoice and send up red flags throughout our system).
And just to put all the cards on the table, here's fakeoutUpdate in its entirety:
private void fakeoutUpdate(GPService.SalesInvoice invoice){ // If bins are already allocated, the next update deletes the allocation regardless of what is sent. // This update is to de-allocate the order while preserving the bins we know about already so they'll // save properly later in the process. GPManager.Service.UpdateSalesInvoice(invoice, GPManager.GetContext(), UpdateSalesPolicy);}
There's another potential bug if you get another user updating the same sales invoice from a different machine between the time the fake is run and the actual update. Fortunately, the total time between the two updates is literally microseconds. Indeed, our order processor says that there is no noticeable difference in the time it takes to commit updates between the new process and the old one. Subjective, I know, but good enough.
I find it odd that such simple and universal bugs have made it into the release of the product. It speaks poorly of the testing done at Dynamics headquarters. These aren't bugs that should have been able to slip through a minimally competent QA process. It's clear that nobody tested updating invoices in a multiple bin scenario. At least, not in a way that checked that the bin allocations survive the update.
I also find the lack of information out there disturbing. It makes me feel like I'm the only developer using Dynamics GP Web Services for anything beyond the most basic functions. I know that can't be true, but you couldn't prove it by the amount of chatter on the interwebs. I've noticed before that business line developers are under-represented out here and this reinforces that feeling. The only Dynamics blogs I've been stumbled across seem to be vendors and/or supply channel/party line outlets. These blogs talk enough about the abomination that is Dexterity, but almost none at all about alternatives like eConnect or GP Web Services.
author: Jacob | posted @ Tuesday, August 10, 2010 4:05 PM | Feedback (0)
My apologies if you've tried to access my personal blogs recently. I've been inundated by comment spammers and it has been a tremendous pain in the buttocks getting them straightened out. For a while, I was getting only a half dozen or so a day. Short comments about what an amazing blog/post it was and that they'd definitely be back and/or bookmark/subscribe.
I could manually delete them without too much inconvenience for a while. Lately, though, there's been a staggering increase in these weasels so I've adopted measures a little more… drastic.
I noticed that most of these spammers shared some distinctive characteristics. Many of them put down the same email address, for example. I also noticed that there were only three or four websites generally involved. Since the spam exists for the purpose of Google pagerank manipulation, the website is probably the important thing to note.
Now, I looked for a BE.Net extension that'd do this already. Unfortunately, most of the comment filters I found were tied into Akismet or some other blog filter service. That's more overhead than I really want (in terms of configuration, registering, and complexity etc.). All I really need is something to check the email address, website, and maybe IP address against a known blacklist I can maintain myself. That shouldn't be difficult, right?
On the surface, these things weren't that hard to accomplish. BlogEngine.Net has some quirks, though, that got in my way until I figured them out. For those interested, I'm going to explain them here. If you want to skip the gory details, head down to the next section. Or if you just want the extension, download it, pop it into the App_Data/Extensions folder and season to taste.
My first impulse was to look at the Comment object for useful events to extend. Comment.Validating looked like a good candidate so I tried that one out. Unfortunately, that event never got hit on my blog. It took me a bit to realize that this is because I don't actually validate comments. Validating comments is a setting where a comment doesn't show up until it is approved. Since I only do blog maintenance once a day or so, I don't want to prevent comments from showing up for that long. Validating comments would pretty much stop discussions in their tracks and I don't want that.
Once I remembered that comments are managed on the Page object, things went much better. The Page.AddingComment event turned out to be the one I wanted.
This is the one that held me up the longest. ExtensionParameters can be assigned types that include things like "DropDown" and "ListBox". That seemed like exactly the kind of thing I could use for my filters. You see, each filter will be of a limited number of valid types: "Website", "Email", "IP Address", or "Length" (I added Length when I noticed that all these messages are really short and I might want to account for that in my filter).
Unfortunately, these ParamType values are a complete red herring for tabular data storage. I noticed that BE.Net wasn't actually storing my selection when I tried to add filter entries. The thing is that BE.Net stores tabular values on each parameter in the DataStore and only maintains a link to them by the order in which they appear. So my parameters in the DataStore look like this once saved:
<Label>Filter Type</Label>
It looks to me like list types (DropDown, ListBox, etc.) were mainly implemented with scalar settings in mind rather than tabular settings as this needs to be. This is unfortunate, but I can't see an easy way to alter the architecture to enable list types easily. I could create my own custom admin page for the extension (and I still may) but that's more work than I wanted to do to get this running.
So my comment extension has been up and working for a day or two now and things have calmed down a lot. This is a good thing. I can't say that it is extensively tested for the simple reason that I don't get many legitimate comments on a regular basis.
Configuration is pretty simple as long as you don't typo the Filter Type value. Each filter is its own entry in the tabular list on top.
(Click image to enlarge)
When I noticed that it still looks to the user like their comment is saved (because the comment is still part of the page object, it just isn't saved to the DataStore), I had an inspiration. Since the comment is still displayed to the person who posted it (though not to anyone else), that's an opportunity to make sure that someone running afoul of my length requirement doesn't end up wondering what happened. Plus, it gives me a chance to tell spammers that they've been noticed (yeah, that's of dubious value and I may rethink this, but for now, it just makes me feel better). If you enlarged the image above, you'll see that there are templated values that will be used to replace the comment content. I can be as nasty as I want and the only ones who see it will be the spammers—though you'll probably want to take it easy on those who stumble on your length filter (if any).
A day or so after this filter went into effect I started to get new messages. These are clever little plays for sympathy saying things like "my comment got eaten but anyway… <regular spiel here>". Or another "my blog is getting lots of comment spam, do know any way to help?" The website links were still classic spam sites so these weren't real users looking for help. Cheeky little locusts, aren't they? Seriously, someone with the right skills needs to hunt these bastards down and rearrange key organs into innovative new patterns.
author: Jacob | posted @ Tuesday, July 14, 2009 1:33 AM | Feedback (4)
The multi-blog data provider for BlogEngine.Net has been taking up a lot of my brain space lately—to the point that I'm able to announce that it is installed and working "in the wild" on a hosted site (though not in anything like a heavy-load situation). I now have a copy of both my dev site and my personal site up and running from the same directory (and the same database). Frankly, I didn't think it'd be as easy as it was. This success prompted me to create a 2.0 release (that is now up on the CodePlex site).
My main fear was with the heavy use of static variables in BlogEngine.Net. You see, BE.Net loads all the data into memory using static List variables. I found this out when I went looking for the best way to store a BlogId (so that it didn't have to parse against an Url every time a request came through).
While there are pros and cons to keeping your entire blog in memory (pro: speed and ease, con: memory bloat and a large delay on any request that triggers a data load), my concern was how an application would react when it had to serve two sets of data. Fortunately, it seems that even when two sites share an application pool on IIS, they still keep their static spaces separate. I'm not sure what I was going to do if it didn't but I was spared the tragedy.
Installing the blog provider mainly involves copying the binary into the /bin directory and then updating the web.config to point to the right driver. There are three providers in your web.config that are affected.
The blog provider handles the blog data. Settings, posts, categories and suchlike. Add the provider and update the "defaultProvider" tag and you're ready to go.
<blogProvider defaultProvider="SQLBlogProvider">
<add name="SQLBlogProvider" type="BlogEngine.SQLServer.SqlBlogProvider, BlogEngine.SQLServer" connectionStringName="BE"/>
The membership provider handles user authentication and management (stuff like changing passwords and such). Technically, you don't need to change this, but if you don't the users will be the same across blogs (not a problem if you aren't multi-blogging). I frankly haven't tested if a mixed-configuration actually works but it should. Again, add the provider and update the "defaultProvider" tag and you're ready to go.
<membership defaultProvider="LinqMembershipProvider">
<add name="LinqMembershipProvider" type="BlogEngine.SQLServer.LinqMembershipProvider, BlogEngine.SQLServer" passwordFormat="Hashed" connectionStringName="BE"/>
The role provider handles authorization and what users are assigned to which roles. Again, you don't technically have to change this if you don't need it. Also again, it's simply a matter of adding the provider and changing the "defaultProvider" tag.
<roleManager defaultProvider="LinqRoleProvider" enabled="true" cacheRolesInCookie="true" cookieName=".BLOGENGINEROLES">
<add name="LinqRoleProvider" type="BlogEngine.SQLServer.LinqRoleProvider, BlogEngine.SQLServer" connectionStringName="BE"/>
To set stuff up for multiple blogs, you'll need to run a script or two in your database and add a tag to all the providers. There are two script files (included in both the binary and source files), one for setting up the initial database changes (DatabaseSchemaChanges.sql—mostly adds tables) and another for adding the base values for a new blog (AddNewBlog.sql).
I wanted to make this easier by having the driver do the updates for you. That may still happen in the future, but since BlogEngine.Net itself requires manually running a script if you want to use the database provider I decided not to sweat it too hard. Presumably, anyone running in a database has to be running scripts manually anyway so this isn't going to be a show stopper.
The provider will run just fine after running either script, even if you aren't using multiple blogs. In other words, just because the database changed doesn't mean that the single-blog installation is hosed. The exception to this is the "be_Settings" table. If you're going to run for a while with a single-blog after running the first script, you'll want to add a default to the BlogId column so it doesn't choke when you insert and update settings.
Both scripts are "templated" so you can change key factors (a table prefix on the first and a couple of blog values in the second). Filling in the template is a matter of hitting ctrl-shift-M in Query Analyzer or SQL Server Management Studio. That'll bring up a prompt for what values you want those template variables to have.
The final thing to setup is to add a multiblog attribute on the providers. That'll make your providers look something like this.
<add name="SQLBlogProvider" type="BlogEngine.SQLServer.SqlBlogProvider, BlogEngine.SQLServer" connectionStringName="BE" multiblog="true"/>
The provider selects the blog it wants to deliver based on three configured values.
One thing I added (at the provider level) is that when a post comes in without any tags, the provider takes a moment to scan for tags in the post body. This is a feature I did the initial work for in Subtext so porting it over was a matter of a couple minutes. Any time a post is inserted into the database, the provider checks if it has tags yet. If no tags are present, it will scan the content for appropriate anchor markup (like those produced for Technorati tags). That means that on import, my posts all had their tags correctly populated—saving me a lot of extra work (or face losing tags on imported posts). That I was able to avoid the brain-damaged tag handling of BlogEngine.Net is just a bonus (they lower-case tags on creation and then re-capitalize them when serving them up).
As I said, this should get you set up. Since I used this blog provider from the start on both my blogs, I can verify that the import tool works just fine in a multi-blog configuration. As far as BlogEngine.Net is aware, it's doing the same stuff it always has. Indeed, the only change I made from BlogEngine.Net's standard v1.4.5 release was in UrlRewrite.cs to allow links produced by Subtext to still work (so I don't throw errors on old links).
else if (url.Contains("/POST/") || url.Contains("/ARCHIVE/"))
I submitted a patch at one time to have this hit the base source code but apparently it wasn't deemed worthy.
Also, I found that running the provider in IIS7 is a bit tricky. Since BlogEngine.Net loads extensions from the database on application start you'll get errors if you are configured for "Integrated" mode. That's because "Integrated" mode (quite properly) fires the application start event before the HttpContext.Request is populated (which is what I'm using to determine what blog is being requested). Setting the application pool to "Classic" mode will solve this "problem".
My blogs are still running Subtext at their base addresses. I'm still not quite ready to take the plunge on BlogEngine.Net. I am, however, undoubtedly one step closer.
author: Jacob | posted @ Thursday, April 02, 2009 5:26 PM | Feedback (17)
So I have a working LINQ to SQL provider for BlogEngine.Net. Now what? Given a little spare time, how about I see if I can't use it to support running multiple blogs from the same installation? More importantly, see if I can use it to support running multiple blogs from the same database?
Doing just that turns out not to be all that difficult.
The current architecture for BlogEngine.Net's data already has a bit more cohesion than it technically needs. All the objects have their own individual Ids and those Ids are used to relate objects to each other (though there is one exception). Since every object already has its own Id (usually a Guid), splitting objects into separate blogs isn't the chore it might otherwise have been.
There are two options when it comes to dividing items up into multiple blogs. First, each object can have a column added to its table to indicate which blog it is associated with. Second, you can create a cross-reference table that associates a blog Id with the object Id for the blog.
Columns My initial impulse in most cases would be to add a BlogId column to the tables where it is needed. The reason is simple: objects belonging to the blog are in a true parent-child relationship and that relationship is generally best expressed as a field on the child indicating its parent. The relationship can (and really should) be enforced with a foreign key constraint on the column to ensure that the relationship is intact.
Cross-references Having cross-reference tables is a bit more problematic and carries with it some maintenance and performance concerns. Not only does it force a join when you want to read the objects for a specific blog, but it means that insert, update, and delete commands now have to involve two tables instead of just one. One advantage of cross-reference tables is that they're easier to extract back out if you need to devolve your data. Additionally, foreign key constraint integrity is triggered when the cross-reference entry is created instead of on your blog objects themselves—making your touch a bit lighter if you have other actors in the system.
Complicating Things No decision is best for every occasion, and when it came time to design how I wanted multiple blogs to work, I was really reluctant to mess with the native tables of BlogEngine.Net. I'm not sure if my hesitation is a matter of respect for a project I'm not involved in or if I'm just being unreasonably squeamish, but I eventually chose to go the cross-reference route. My main reasoning is that I wanted my intrusions to remain light and easily devolved.
Now, normally, adding a super-structure on top of an existing infrastructure is a real pain. Editing all your SQL statements manually becomes an exercise in precision string manipulation and if you're working through stored procedures… ugh. Linq made this really easy.
Here's an example from the FillProfiles method of the blog provider.
var profileData = from p in context.Profiles
select p;
if (isMultiBlog)
profileData = from p in profileData
join bp in context.BlogProfiles on p.ProfileID equals bp.ProfileId
where bp.BlogId == Utils.GetBlogId()
The initial select is good for the general case. It pulls all the objects from the Profiles table. Adding a filter when we have multiple blogs is added in the if clause. Note that the second select references the first ("from p in profileData"). Linq knows that the second "from" is a refinement of the first and puts them together logically. Since Linq defers execution of the query until it's actually used, the query sent to the server includes the full constraint (i.e. filtering happens on the database). Here's the statement that's actually sent.
SELECT [t0].[ProfileID], [t0].[UserName], [t0].[SettingName], [t0].[SettingValue]
FROM [dbo].[be_Profiles] AS [t0]
INNER JOIN [dbo].[be_BlogProfiles] AS [t1] ON [t0].[ProfileID] = [t1].[ProfileId]
WHERE [t1].[BlogId] = @p0
This method ensures that you only take the hit of the join if you are in a multi-blog setup. And without pulling everything to the client.
I had some fun with the Settings table because it is an exception to BlogEngine.Net's Id rigor. It has interesting impact on the Linq situation, but I think I'll give it its own (short) post later.
So I tested this in my own home-grown environment and it seems to work as expected. In consequence, I've created a new release at the project homepage. I'm calling it a beta, though it barely warrants the label. I worry that it has only been tested in a single environment. If you're a hearty soul and a BE.Net user, please give it a go. I'll be spending some time getting it set up and tested in an actual public setting with my personal blogs here shortly. As always, I welcome feedback either at codeplex or comments or via email.
author: Jacob | posted @ Friday, March 27, 2009 5:00 PM | Feedback (0)
I'm at Convergence this week in New Orleans. If you're unfamiliar with the conference (and don't want to follow the nifty link), all you really need to know is that it's Microsoft's convention for their business solutions products. For me, that means Dynamics Great Plains.
I bring this up because in the last session I attended yesterday, Louis Maresca mentioned a problem I remembered having with GP Web Services. GP WS has a serious problem when you first instantiate the proxy object: it can take seconds (over 30 on our older systems—I put a timer in just to verify) to instantiate the web service proxy. The reason for this is that .Net queries the service to pull down the available methods and objects on instantiation. Since there are very many of them available in GP Web Services, the query and xml serialization adds up to quite a lot.
Now, his solution was very clever, but involved creating a new web service to slim down the contract retrieval. My solution was to saddle up and use WCF. You see, WCF doesn't do silly things like query for contracts it already knows full well about. I cracked how to use WCF with GP Web Services about a year ago and I haven't looked back since.
In that session last night I realized that others might want to know what it took to get it working (and thus a blog post was born…) I'm not going to go though creating the WCF bit. It's pretty straight forward and explained all over.
Crap, I find I can't actually proceed without at least giving an overview.
Okay, now that I got that out of my system there are two things that prevent WCF and GP Web Services from playing nice together.
Since GP WS uses your windows identity to validate things like roles and permissions, your client needs to send the correct identity or "bad things can happen"™. In VS 2005 web services, this was a simple matter of setting .UseDefaultCredentials to true. In WCF it's a good bit more complicated. It's a mirror of remotely printing Reporting Services using WCF, though, so techniques used there are applicable (though slightly different).
First, you have to let the binding know the correct security mode and transport. I did this in a basicHttpBinding in the <security> section:
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" />
I came at this setting obliquely and after much trial and error. I'm not sure why clientCredentialType="Windows" didn't work against GP WS when it worked with Reporting Services. Probably something quirky in our environment.
This alone is not enough, however. The binding setting is just the contract. To actually use the correct credentials, your proxy has to be told what to do. Not difficult, but easy to overlook when you're coming from a 2005 web services background. Here's all it takes:
DynamicsGPSoapClient service = new DynamicsGPSoapClient();
= TokenImpersonationLevel.Impersonation;
Once that's all taken care of, you're set to go. Those two lines of code are processed pretty much instantaneously on even our slowest clients, so problem solved. Almost.
Error handling hung me up for a while and was the final hurdle to being able to truly implement WCF with GP WS. I was so excited when I finally figured it out that I blogged it at the time. The key point is that GP WS wants to check a user's authorization to view errors before giving up the details of what happened so you have to hit the web service again for details. Thus, while the status message is informative, you only get a GUID for detail in the initial error. This is not a bad thing, but it leads to difficulties when putting together your excuses to the user—particularly when WCF doesn't make it easy to get at the details of an untyped FaultException.
From here, everything is pretty much the same. You have your objects in the domain you specified in the "Add Service Reference" dialog given above (GPService in my screenshot). Your proxy object has the methods you can use.
author: Jacob | posted @ Wednesday, March 11, 2009 9:20 PM | Feedback (0)
Every now and then I get to doing something just because... well, because I can. These projects usually atrophy before becoming anything usable and serve more as a way to explore and practice than anything else. Usually. My latest tangent actually got to a state where I can let it loose in the wild and it'll probably actual do what it is supposed to do.
Let me be perfectly clear up front: I don't actually use BlogEngine.Net at all. Anywhere. I'm still a Subtext guy when it comes to blogging software. BlogEngine.Net still lacks critical features and that prevents me from using it as yet (primarily running multiple blogs from a single installation/database).
That said, BlogEngine.Net is a lovely little product with a lot to like about it. The extensibility model is extremely easy to use and flexible. The theming doesn't suck. And its architecture is easy to navigate/understand even while it makes investments in areas I consider likely to payoff.
While I like the product, the data access bugs me more than a little. It uses a provider model and includes built-in XML and database providers. These are good things. For flexibility, the database provider uses System.Data.Common and the DbProviderFactory with string-built commands. This structure allows BlogEngine.Net to be able to use any database that has a .Net data provider (including things like MySQL, SQLite, or VistaDB). Incidentally, they downplay (unintentionally?) this feature on their website saying in their FAQ that they support XML and "the SQL Server provider".
At any rate, here's their SelectPage implementation as an example
public override Page SelectPage(Guid id)
Page page = new Page();
string connString = ConfigurationManager.ConnectionStrings[connStringName].ConnectionString;
string providerName = ConfigurationManager.ConnectionStrings[connStringName].ProviderName;
DbProviderFactory provider = DbProviderFactories.GetFactory(providerName);
using (DbConnection conn = provider.CreateConnection())
conn.ConnectionString = connString;
using (DbCommand cmd = conn.CreateCommand())
string sqlQuery = "SELECT PageID, Title, Description, PageContent, DateCreated, " +
" DateModified, Keywords, IsPublished, IsFrontPage, Parent, ShowInList " +
"FROM " + tablePrefix + "Pages " +
"WHERE PageID = " + parmPrefix + "id";
cmd.CommandText = sqlQuery;
cmd.CommandType = CommandType.Text;
DbParameter dpID = provider.CreateParameter();
dpID.ParameterName = parmPrefix + "id";
dpID.Value = id.ToString();
using (DbDataReader rdr = cmd.ExecuteReader())
if (rdr.HasRows)
page.Id = rdr.GetGuid(0);
page.Title = rdr.GetString(1);
page.Content = rdr.GetString(3);
if (!rdr.IsDBNull(2))
page.Description = rdr.GetString(2);
if (!rdr.IsDBNull(4))
page.DateCreated = rdr.GetDateTime(4);
if (!rdr.IsDBNull(5))
page.DateModified = rdr.GetDateTime(5);
if (!rdr.IsDBNull(6))
page.Keywords = rdr.GetString(6);
if (!rdr.IsDBNull(7))
page.IsPublished = rdr.GetBoolean(7);
if (!rdr.IsDBNull(8))
page.IsFrontPage = rdr.GetBoolean(8);
if (!rdr.IsDBNull(9))
page.Parent = rdr.GetGuid(9);
if (!rdr.IsDBNull(10))
page.ShowInList = rdr.GetBoolean(10);
return page;
I want to reiterate that I'm not ripping on their choice to use this data access methodology. If you want the flexibility to use any .Net supported data provider without a third-party dependency, this is how you get it. You could optimize some of the stringiness, but with trade-offs.
That said, I don't mind being tied to SQL Server and if I'm going to muck with the data layer (like, say, if I'm going to attempt multiple blogs from a single application instance) I want something simple that I can use without all that extra goo. I looked for any hint that this might have been done already, but I couldn't find anything. It looks like I'm the only one with this particular manifestation of brain damage.
Since configurable table prefixes are a desirable feature and since that's easier to do in Linq to SQL I figured it'd be best to go that route. It was good to get the table prefix stuff into a working project and have it work about as I expected it to.
Implementing the BlogEngine.Net blog provider turns out to be pretty easy in Linq. Ditto the Role and Membership providers. I tried to stay as close as possible to the DbBlogProvider. Even so, I found that some of the admin components are picky enough that even little things could bite me (the category editing page blows up if you leave category descriptions null, for example).
For compare and contrast, here's my SelectPage method using Linq to SQL
Page page = null;
using (Data.BlogDataContext context = getNewContext())
Data.Page pageData = (from p in context.Pages
where p.PageID == id
select p).FirstOrDefault();
if (pageData != null)
page = new Page()
Id = pageData.PageID,
Title = pageData.Title,
Description = pageData.Description,
Content = pageData.PageContent,
Keywords = pageData.Keywords,
DateCreated = pageData.DateCreated.HasValue ? pageData.DateCreated.Value : DateTime.MinValue,
DateModified = pageData.DateModified.HasValue ? pageData.DateModified.Value : DateTime.MinValue,
IsPublished = pageData.IsPublished.HasValue ? pageData.IsPublished.Value : false,
IsFrontPage = pageData.IsFrontPage.HasValue ? pageData.IsFrontPage.Value : false,
Parent = pageData.Parent.HasValue ? pageData.Parent.Value : Guid.Empty,
ShowInList = pageData.ShowInList.HasValue ? pageData.ShowInList.Value : false
return page;
So I got the thing working and thought I'd open it for "the community". Since BlogEngine.Net is on CodePlex, that was a natural choice. Anyone sharing my peculiar proclivity is invited to head on over, take a poke and let me know what can change for the better. Or better yet, submit a patch. Or better, better yet, join the project. (also: CodePlex's recent transparent svn compatibility is awesome! When did that happen?)
If you do poke at the project, some forewarning. First, I don't have unit tests for this and don't plan on any (I'm not against using them, I just don't want the headache of creating them myself). Data access is more in the realm of "integration testing", so I'm not sure there's much you can really do that's actually useful. It might be different if BlogEngine.Net had a suite of tests I could use to validate my providers against, but...
Second, I haven't gone out of my way to do a lot of commenting. This is deliberate. These methods are short, should be self-explanatory, and since they should be hidden behind a provider I didn't even bother with the typical XDoc stuff. Anything directly accessing them such that intellisense comes to bear is doing something wrong...
In the end, this is the ground-work to remove an (admittedly trivial) barrier in working with BlogEngine.Net. I hope to help move as much as possible into the database in order to support things like multi-blog configurations. BlogEngine.Net hasn't been very disciplined in its storage layer and XML really is the default medium. Things like referrer tracking don't use a provider at all so you really can't (yet) get away from XML files in your App_Data directory (and hence, read/write permission configuration). Since I want that to change, I'm going to see if I can't get that going a bit.
author: Jacob | posted @ Wednesday, March 04, 2009 1:11 PM | Feedback (7)
I had an interesting problem crop up trying to run my own application this week. We have a routine that uses an excel spreadsheet to import orders into Dynamics GP that includes some twists that aren't handled well by Integration Manager. Since the application runs from the network (using ClickOnce) and because these orders can be substantial and represent a commitment of corporate resources, we want some control over who can run them. Specifically, we use Active Directory group membership with hard-coded/defined groups.
One of the groups I want to allow is Domain Admins. And yes, this is a kludge. All three members of our small IT shop are Domain Admins—mainly so that we can act as backup when the others are unavailable. It's a handy kludge, though, so lump it. Unfortunately, when running from my machine (running Vista), the user token being used to check Identity.IsInRole() wasn't admitting that I am, in fact, in the Domain Admins domain group
This is, by the way, the first I've run into an inversion of Works on My Machine™.
It wasn't terribly difficult to figure out what was wrong. The key to the problem is that Vista UAC (which I actually rather like because I want to know when programs undertake certain activities) creates a "split token" when you login using an account with admin privileges. The user actually runs using the filtered token that removes the dangerous things and only elevates (with user notification and approval) when those privileges are actually needed.
So when I asked WindowsIdentity.IsInRole("COMPANY\Domain Admins") it told me that it's never heard of that role and certainly I'm not a member of it. This was disconcerting.
Now the problem goes away if you start Visual Studio with "Run as Administrator" or start an application with a shortcut with that setting. Which works fine (not great) while developing (if you remember to start VS as administrator) but eventually I got tired of it and sometimes I want to run the deployed app from my box. There's just one small hitch. Remember that I mentioned that we deploy the app to the network using ClickOnce? It turns out that there's no good way to start a ClickOnce app with elevated privileges. Googling around (and even checking Stack Overflow) I found some people who wrote what were essentially batch files or ran services that could then be used to elevate processes either to run ClickOnce apps or to allow ClickOnce apps to do stuff that requires elevation. But really, that's a lot of hassle for something I just knew had to be simpler.
After beating my head on the problem for a bit, I eventually took a step back and asked myself that crucial dev question: "What am I actually trying to accomplish here?" I need to remind myself to do that sooner when I find myself "brought to Point Non Plus" (as Georgette Heyer's characters might say). It turns out to be a good question and one that led to the "Duh" moment I share with you now.
Since I'm not actually doing anything that requires admin privileges, going for process elevation is a complete waste of time. All I really want to know is if the current user is part of a specific Active Directory group. Didn't I see something about .Net Framework 3.5 and managed domain objects? Why yes! Yes I did!
The nifty little buggers are in System.DirectoryServices.AccountManagement and if you do anything with Active Directory domains you owe it to yourself to give this namespace a once over. Here's what I ended up with:
bool isAllowed = false;
WindowsIdentity wi = WindowsIdentity.GetCurrent();
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "COMPANY"))
UserPrincipal up = UserPrincipal.FindByIdentity(pc, wi.Name);
GroupPrincipal gp = GroupPrincipal.FindByIdentity(pc, "Domain Admins");
if (up.IsMemberOf(gp))
isAllowed = true;
This worked right out of the chute. Well, getting the right AD group membership didn't want to work when using the Principal.IsMemberOf(PrincipalContext, IdentityType, string) overload, but pulling down the actual GroupPrincipal looks cleaner anyway, I find.
author: Jacob | posted @ Friday, February 13, 2009 1:56 PM | Feedback (3)
One of the things I am seeing less of lately is the understanding that reasonable people can and will disagree with one another—without either of them being any the less reasonable or intelligent for doing so. It seems to me that people become so invested with the "rightness" of their ideas that they deny the possibility that those who disagree with them may be equally intelligent and well-informed. You see it a lot in politics, but I think that this attitude has crept into development discussions as well.
I saw a manifestation of this in action after a recent Stack Overflow podcast wherein Joel had the temerity to question Robert Martin's SOLID principles (SOLID was the topic of a recent podcast with Scott Hanselman that Joel had apparently heard). I highly recommend both podcasts. It didn't take long for some bright stars in the Alt.Net universe to talk about Joel jumping the shark or the state of his imperial wardrobe. I'm not sure why the impulse to denigrate those who disagree with you is so strong, but it appears to be nearly universal. We go from the belief that somebody is wrong to the conclusion that they are incompetent or ignorant without taking time to draw breath, really.
I think this impulse is not only wrong, but damaging. It represents a voluntary limitation of our ability to engage in important dialog and stretch our understanding.
One crutch of those who participate in this hidden hubris is the belief that people who disagree must be missing data. You can see this most commonly when someone tells you to "educate yourself" or its milder form "try it and you'll see". The underlying message in those statements is that if you knew what they know, you'd do what they do.
And that may be correct. It really could be the case that someone is missing data and if they had that data they might agree. Since software development is so change-driven, much of development blogging is motivated by the desire to teach others things they might not have heard about before. You have to honor the often unrewarded efforts of those who take the time to put information out there for the benefit of those seeking education.
The problem is that telling someone who questions your tools or methods to educate themselves is arrogant, even if you are completely sincere and honestly well-meaning. You see, there are really only two possibilities for someone questioning you: they lack data or they have arrived at a different conclusion after weighing the data themselves.
In the first case, telling them to educate themselves notifies them of your superiority (you are in possession of data they lack) at the same time you deny access to yourself as a resource (you are directing them elsewhere for acquiring that data). It's a dismissive brush off. In the second case, telling them to educate themselves is a judgement of their experience and conclusion without the benefit of explanation or debate. In both cases you are saying that you are better than they are and that they shouldn't be allowed to participate in the discussion as a result.
If you honestly believe that someone disagrees with you due to lack of information, a better response would be a series of questions or even challenges geared towards examining their point better. "Have you considered" questions or "I disagree because" statements are more helpful; they give others the chance to respond and have the courtesy of taking someone seriously enough to invest in the discussion.
What if I'm already educated and I still disagree? What if I've done the recon, seen the scene, danced the dance, bought the souvenir and I still beg to differ with your Great Truth? How can two intelligent people look at the same data, having access to the same information, and arrive at two legitimately different conclusions?
Allow me to educate you. (heh)
You see, most decisions are complex and involve competing principles. Do I take the time to add an abstraction layer that will be useful later or do I YAGNI my way through with the simplest solution that works right now? Do I hassle with System.Data.Common to support multiple database providers or allow a strong dependency on SQL Server? Do I use test first to drive out my design or am I confident that my planned design is decoupled enough and tests ex-post-hackto will be adequate? All of these decisions break down into factors that we weight according to our experience and expectations.
I'll illustrate what I mean. Lets take, for example, deciding if Georgette Heyer is better than Meg Cabot. It can be argued (and I would, indeed, so argue) that they have comparable ability with characterization, prose, story, and plot. However, Meg Cabot sets her characters in modern settings and Georgette Heyer's books are chiefly set in Regency England. Two people could easily disagree over which author is best if one has a strong weight on "historical regency setting" without either being any the less intelligent or in need of education.
Back to software development. Consider some of the factors that might go into deciding to use TDD.
How you weight each factor will determine your judgement of TDD. Someone who is not worried about forcing decoupled design (either because decoupling doesn't pay off in their environment or because they feel they can achieve decoupling without force) will be less likely to chose TDD for their project.
And it gets even more complicated when you realize that each factor can, in turn, be comprised of additional factors with their own weight and trade offs (you could easily break "decoupled design" down further, for example).
Learning to look for underlying principles and the weights that others may apply can be interesting as well as useful. More importantly, it opens up the gray areas and opportunities for honest disagreement (without denigration) that are vital when working with IRealWorld.
As software professionals, we owe it to ourselves, our employers, and our clients, to be educated in our craft. That's a not inconsiderable burden in a field that grows by leaps and bounds year after year with no sign of slowing any time soon. It is hard enough learning all the concepts, patterns, and practices (not to mention tools, environments, and platforms) that it is often tempting to find a core of experts that you rely on to make decisions for you (and there is some benefit in doing so initially as you come up to speed on the intricacies of our field).
But to be truly educated, you have to go beyond what your experts say and learn about the principles that exist underneath. That's extra work but more importantly it is extra responsibility. It may be that when you break a practice down into its constituent principles that you will find yourself in a situation where "Best Practices" aren't, in fact, best. To me, it is the ability to not only make that determination but to then act on it that truly makes a "professional".
author: Jacob | posted @ Friday, February 06, 2009 7:17 PM | Feedback (5)
Original Template Design: Leevi Graham
Adapted Design: timheuer


text:
When I first started to manage the Twitter account here, I tried to take it from the perspective of "all business". I didn't make jokes, laugh, or say snarky things. I wanted to be this little pillar of customer service and professionalism that would woo and wow the masses, and bring the flocks to me. I was wrong – but that's okay. I guess I didn't exactly get it at first. There's a big difference between the old fashioned ways of customer service and what Twitter (or any social platform) can do for a company.
I'm sure there's more and there will always be more to learn. Using social media with customer service is one of those things that will be forever evolving. It's completely different today than it was six months ago and then it will be six months from now. What have you learned about customer service from social media?
Business Communications
The past decade for the airline industry has been a spiral into near oblivion. ATA president and chief executive, James May, described it as "the lost decade," as, first, fear of terror choked out travelers, then, fuel prices spiked coming into a global recession that left people pinching pennies and airlines gobbling up all profits from the previous decades just to stay afloat. Now, the carriers appear to be finding their first warm embrace in summer 2010. Southwest airlines reported a $112 million profit in the second quarter 2010, a 23 percent jump that surpassed forecasts. Last week, Delta Air Lines posted its best second quarter since the advent of the lost decade. The carrier profited $467 million from the previous year's loss of $257 million. In fact, it is predicted that all U.S. airlines will end 2010 in the black, a surprising assessment given the losses in 2008 and 2009. The factors bolstering the turnaround are simple supply and demand. When the economy was in its stupor people weren't flying. The airlines were forced to ground more flights to cut costs. This resulted in a degrading feedback cycle. Now that the economy is making a run, more people are taking to the skies. Business travelers lead the way as companies allotted more money for travel after the difficult recession. Then more and more leisure travelers came out for the summer travel season. All resulted in less planes being grounded and now airlines have the demand to fill capacity. The result, now, is an increase in fares driven by the demand. US Airlines' first-quarter-2010 fares rose 4.7 percent to a nine-year high. Along with higher fares, summer travelers can expect greater crowds, delays and planes filled to the brim thanks to capacity discipline—all byproducts of the rebound.
The Federal Communications Commission has redefined the classification of "broadband internet", raising the minimum download limit from 200Kbs to 1Mbs. However, this change the FCC said is "long overdue", has sparked discussions about telecom monopolies and pricing models, and put the subject of net neutrality center stage.
200Kbs is an eleven-year-old limit set by the FCC in the days when Dial-Up internet was how the majority of Americans accessed the internet. While changing the definition may seem small and irrelevant to most people, it is actually a powerful tool in this online social media and internet-integrated world. Previously, Internet Service Providers were able to use the low definition of broadband to minimally conform to the FCC's National Broadband Plan to provide affordable, high-speed internet to every American.
But even as the US internet infrastructure is becoming stronger and less expensive, ISP and telecoms are raising prices--ATT's new $25 for 2 gig/month data plan for example. And while higher on internet speeds has brought out telecom complaints of additional expenses to build infrastructure to match, it also revealed telecom pricing and control strategies for tiered access to the internet. Throttling access to the internet is a violation of the freedom of internet, Net Neutrality Act.
While the only concrete occurrence is a higher broadband speed definition, with the upcoming Google Fiber Network and the fierce telecom pricing wars, it will be a while before the full impact is seen on the face and structure of the internet.
There are a lot of different reasons a company will host a conference call. It could be to announce a promotion, have
Some examples of I-Centric presenting will be when you say phrases that have a personal focus, like I have or I feel. In a We-Centric conference, you'll be referring to a lot of things in the third person or using we. So how do you know what focus to take? As I've said before, on a conference call you only have the ability to use words and tone to set a mood.
Set the mood with an "I-Centric" presentation if you are:
Invited to speak on the conference call. You're there because you have some information, and people want to hear how what you've done worked for you.
Accepting a promotion or a new position. You want to address that you're excited and that you're looking forward to working with everyone.
Presenting research you did. Sometimes, what you're showing everyone is something that you've done on your own, so "I-Centric" words are completely okay.
Set the mood with "We-Centric" phrases when you are:
Accepting a promotion or a new position. Yes, I realize that I suggested you use I-Centric words for this situation also. The truth of the matter is anytime you accept a promotion or new position in your company is a time that you should enforce the ideas that you're all going to be a team. It's important that everyone walks away knowing you're excited about your new position and that you look forward to collaborating with a new team.
Updating on company policy. When policy changes are made, it's not just the employees who are affected. Everyone will be affected by changes in a company. When announcing them to a group of employees you need to make sure they understand that the management will not be immune to the changes.
Status meetings. When you're just updating members of your company or group with where you stand on a project or just in general, you should take a We-Centric approach. Any good things that have stepped forward with the project, everyone has a small part of the success – as well as any failures.
The bottom line between using a We-Centric or I-Centric focus is that most of the time, you'll want to use a mixture of both, and depending on what you have to say, it could affect the way you say it. How are you using "we" and "I" to set the mood on your conference call?
Business Communications | Conference Calls
AT&T has made an aggressive bid for the Windows Phone 7, repeatedly supporting the technology and Microsoft's progress.
Now, AT&T has announced that they would be the main provider of Microsoft's upcoming device.
"We'll be the premier carrier for Windows Phone 7," a spokeswoman wrote in an e-mail to PC World.
The assertive statement shows more confidence than other providers—most conspicuously Verizon—who are likely hanging back to see the results of the launch before jumping headlong into the fray.
Perhaps even more telling have been reports that AT&T signed up to buy 8 million WP7 devices last week. The buy would add a massive portion to the 49.1 million smartphones currently in use in the U.S.
Both Verizon and Sprint-Nextel have kept mum about their plans for the WP7.
While Verizon and Microsoft likely have some latent rancor after the Kin capitulation, all carriers are likely poring over reactions by developers, weighing their reviews and testing the WP7's merit.
Some of the outstanding demerits with the WP7 include the lack of multitasking, no copy-and-paste and not native twitter agent, according to ComputerWorld.
The AT&T announcement comes amid clamor that AT&T's soon-to-be-expired contract for the iPhone will result in other providers selling the device, which has been the engine propelling AT&T to the number two spot among cell phone providers.
A steadily-swelling wave of discontentment with AT&T from iPhone users has prompted speculation that the exclusive contract will end in late 2010, which is when the WP7 is slated for release.
However, recent reporting reveals that the contract, signed by the companies in 2007, was not to expire until 2012. It is unknown whether that contract has been amended.
The market results for the second quarter of 2010 were posted last week, and the activity for mobile phone companies reveals an ever-intensifying battle between Google and Apple, along with several other developments in the smartphone realm.
According to comScore, 49.1 million Americans aged 13 and over owned smartphones from Feb 2nd to the end of May, an 8.1 percent increase from the same term the previous year.
The major smartphone operators vying for this market are Palm, Microsoft, RIM, Apple and Google, and each one of these saw a slip in market share except for Google, which seemingly wrested its 4 point increase from its collective competitors. Google bounded by offering the popular Android system through T-Mobile, Verizon, HTC and Sprint.
Apple slipped 1 point to 24.4 percent, Microsoft dropped 1.9 points to 13.2 percent, RIM slipped 0.4 points to 41.7 percent, and Palm dropped 0.6 points to 4.8 percent.
It is important to note that Apple's market share likely waned due to an anticipatory period before the release of the massively popular iPhone 4, which sold over 3 million by July 16th and was the most successful product launch for the storied company.
But mobile devices are only a piece of the pie—about 50 percent of it for Apple—with notebook sales skyrocketing despite the release of the iPad.
Not that the iPad was a bad thing for Apple either. Sales of the iPad have been a hearty 3.27 million by the end of the second quarter, which shows Apple's success in tapping the tablet market, something which has been tried futilely by other companies.
Now a strong argument can be made that Apple has defined the tablet much to the extent that they defined the portable music market with the iPod and its crushing win over the MP3 player.
Yet, while Apple has been making headlines with their flashy (if not controversial) products, the other players have maintained strong footing with savvy marketing practices, frantic mergers and what seems like shear grit.
BlackBerry manufacturer RIM still commands the greatest portion of the smartphone market with 41.7 percent. And Microsoft still earned $4.52 billion in the quarter, outshining both Apple, with $3.52 billion and Google, with $1.8 billion. (Remember, still, that these are before iPhone 4.)
Graph credit to techland.com
Microsoft did this in the absence of a smartphone that competes with those put forth by the other operators and despite having to cancel the Kin.
According to this article in the New York Times, Microsoft's success results from targeting businesses, an industry that is far less glamorous to the media, and therefore, far less likely to make headlines. Nonetheless, Microsoft has a history of selling to both consumers and customers, and without the shiny Macs, iPads, and iPhones their grasp of garnering new customers will steadily drop—even when they sell 150 million Windows 7 OS licenses. Those Windows 7 licenses were mainly purchased by previous Windows Vista users, a disconcerting fact for investors.
The release of the Windows Phone 7 is imminent. The company announced on July 18 that it was in its technical preview stage, and it has received promising-yet-iffy pre-launch reviews. Whether they will get their heads in the game in time for the 2010 holiday release season remains to be seen.
Anyone who knows me knows that I'm a pretty big baseball fan. Last year was a dream season for fans of the Texas Rangers, with a trip to the World Series and a decisive win over the Yankees to win the ALCS. A successful baseball team is a team that runs like well oiled machine, where everyone has a role and a purpose. Managers have to know the strength and weaknesses of their team and everyone has smaller roles, beyond just their field position. The next time you're setting up a conference call try managing it like Ron Washington.
You know that feeling you get when you're sitting in the stands and a guy from your team blasts one over the heads of the outfielders and it disappears behind that green wall. The crowd leaps to their feet in cheers, arms wildly waving, fireworks are going off and you're suddenly hugging the guy next to you. Now imagine how the manager feels when his team can get that kind of reaction out of his crowd. What kind of things are you doing to get ready to knock one out of the park?
Hackers Jailbreaking their iPhones or other mobile devices are not doing so in violation of federal copyright law according to a ruling made by the U.S. Copyright Office on Monday.
The decision says that bypassing a manufacturer's block in order to allow "handsets to execute software applications" will not be viewed as illegal, meaning that users can now download third- party applications that aren't approved by the phone maker or carrier without fear of legal retribution.
The practice has been criticized by manufacturers who say that jailbreaking destabilizes the phones, and Apple, the manufacturer with devices most prevalently jailbroken, contends that the strict vetting process by which apps are approved in the official App Store results in the promotion of higher-quality apps.
However, a relatively small yet sophisticated group of the mobile company's customers have been hacking the phones enthusiastically, heralding benefits such as increased customization, unlimited 3G service and the ability to turn one's phone into a mobile Wi-Fi hotspot that can be used for tethering. Additionally, jailbreaking provides a path for "unlocking" the device, allowing users to operate the phones with carriers other than the one specifically intended for the phone.
According to CNET, by February 2009 400,000 U.S. iPhone users had jailbroken their phones—a relatively small group when set beside the total number of iPhone users in the U.S. (6.4 million in June 2009). Despite the number of jailbroken phones Apple has never sued for terms of use violations.
Bypassing the Apple protection mechanism can void the manufacturer's warranty, but jailbreakers can easily skate the void by performing a hard reset on their devices before taking them in. However, there are other risks, and anyone considering the jailbreak ought to read up on it before embarking.
As of the time of this writing Apple has not commented as to whether it will sue the Feds to controvert the decision.
In the spirit of the fresh legality, though, here is a good site with jailbreak instructions for the latest iOS4.
The iPhone may finally be shucking off its exclusive chains to AT&T. How's this sound: The T-Mobile iPhone.
It sort of rolls off the tongue, doesn't it? And this whole time we thought it would be Verizon.
Yes, According to Cult of Mac, a news site focused on all things Apple, a high-placed executive with T-Mobile said the iPhone is coming to the wireless company in the fall.
Talks between Apple and T-Mobile have apparently progressed, and it's an 80 percent possibility that T-Mobile will have the iphone in Q3, according to the source.
T-Mobile USA is the fourth-largest U.S. carrier with 33.7 million customers, and the parent company, Deutsche Telekom, out of Germany, helped give it some extra clout in the negotiations.
Though T-Mobile lags behind both AT&T, with 87 million subscribers, and Verizon, with 92.8 million subscribers, and many analysts expected that Apple would naturally gravitate to Verizon when the exclusive contract with AT&T expires later this year, the iPhone's hardware is incompatible with Verizon's network.
However, Apple is purportedly working with chipset supplier Qualcomm on hardware that would jibe with the Verizon's CDMA-based network.
Nonetheless, hardware is not the only roadblock. Verizon has aligned itself quite successfully with Google and, over the release of seven Android phones, has forged a strong alliance with the search giant. And with this alliance has come a fierce competitor to Apple and AT&T—one that has launched PR blitzes and ads deriding the iPhone 4's antennagate issue.
All said, an overture to T-Mobile would be a sound strategy for Apple, and given their track record of quickly going to new carriers when exclusive contracts run out oversees, a likely one too.
It would be a good way for Jobs to avoid copping to his competitors over at Google and Verizon. Plus, no one would have to swallow their egos in a massive renovation of corporate alignment.
Apple wants to get away from exclusivity with AT&T; a coalition with T-Mobile would satisfy that need. To boot, the iPhone is compatible with T-Mobile's GSM network. According to the Cult of Mac article, there are still questions as to whether the iPhone will be compatible with T-Mobile's specific 3G bands.
An Apple-T-Mobile coalition will undoubtedly take some working out. It reminds one of a European parliamentary alliance between two similarly-minded yet varied factions, meant to ensure one's dominance—in this case Apple's—while bringing the other onto a more prominent platform—T-Mobile.
Skype is now available for multitasking on the iOS 4, a perk that allows for background VoIP compatibility.
Users with the most updated version of the app will get a pop up message when they're called or messaged via Skype, allowing them access the call immediately. The app can run in the background, meaning that it doesn't have to be open on the screen to detect the calls.
Even when the iPhone is on the lock screen, simply sliding the unlock bar after the popup shows will take you directly to the call or message.
Background compatibility is not yet accessible for video conferencing because of a Terms of Use controversy that cropped up with Fring, which banned Skype earlier in the year.
With the ban set in place by Fring, any ability to video chat on the iPhone was effectively halted, except for Apple's Facetime.
David Byrd
Maranda Gibson
Mary Williams
Debbie Vaught
Receive Posts by Email
Subscribe now with RSS
Follow Us on Twitter


text:
Narrow Your Results
- Category
- Mounts (1)
- Accessories (30)
- Imaging (43)
- Price
- $0.00 - $9,999.99 (75)
- $10,000.00 - $19,999.99 (2)
- $20,000.00 and above (1)
Shelyak Instruments
Shelyak Instruments - Cable RJ9/fils_nus of 3m... Learn More
Model#: SE0039
Shelyak Instruments - Cable RJ11/fils_nus of 3m to connect the sensors/coders... Learn More
Model#: SE0040
Shelyak Instruments - Dome Tracker/PC (RS232) Interface Cable - length 5m
PC RS232 interface cable.... Learn MoreModel#: SE0038
Shelyak Instruments - Spacer for the Star Analyser 100The Star Analyzer 100 has been designed to work with the smallest commonly used sensor chips and the range of camera nose-piece designs commonly encountered ... Learn More
Model#: BA0014
Shelyak Instruments - Two end-of-run switches (to install based on your roll-roof setup)... Learn More
Model#: EL0021
Shelyak Instruments - C-31.75mm adapter - C-1.25" video camera adapterAdapter for C-mount video camera (Watec) on a 1.25 inch telescope eyepiece holder or a Lhires III guiding port ... Learn More
Model#: BA0015
Shelyak Instruments - M42-31.75 Adapter
We propose in option a M42-31.75mm (also called M42-1.25") adapter which allow you to mount the Star Analyser 100 on a SLR (digital or not) equipped with a T/T2 ring; then to mount it on a standard 1.25" eyepiece holder.... Learn MoreModel#: BA0016
Shelyak - C-mount Adapter for Alpy 600 Spectrograph
Adapter to use a C-mount camera on an Alpy 600 spectrograph... Learn MoreModel#: SE0129
Shelyak Instruments - Proximity Coder (M30, PNP closing, 10mm detection distance) for the Dome Rotation Origin
Inductive zero position sensor for Dome Tracker.... Learn MoreModel#: EL0022
Shelyak Instruments - Variable T Adapter - SCT T adapter with variable lengthMount your eShel fibre injection system on a Schmidt-Cassegrain Telescope (typically with a 0.63x focal reducer).Variable system with multiple length spacers ... Learn More
Model#: BA0027
Shelyak Instruments - Short EP holderShort eyepiece holder for Lhires III ... Learn More
Model#: BA0018
Shelyak Instruments - Sentinel wind sensor - Spare part
You can now observe peacefully, remotely or fully automated, with Sentinel watching for your equipment against the weather. Designed with Cyril Cavadore, Sentinel is an astronomical weather station wataching the sky for clouds, rain or snow... Learn MoreModel#: EL0056
Shelyak Instruments - Photographic Tripod Adapter
This accessory allows you to mount your Lhires III on a photographic tripod. Fix it under the Lhires III (standard Kodak thread). Great for public outreach activites!... Learn MoreModel#: PU0024
Shelyak - 3.8° Prism
This 3.8° prism placed in front of your Star Analyser does improve resolution by 20%.... Learn MoreModel#: OP0094
Shelyak Instruments - SX H36/36 Adapter - CCD adapter for Lhires IIIThis adapter works for the following models:-Starlight Xpress SX H35-Starlight Xpress SX H36thread: M72x1backfocus: 19 mm ... Learn More
Model#: SE0088
Shelyak Instruments - Apogee Alta CCD adapter - CCD adapter for Lhires IIIThis adapter works for the following models:-Apogee Altathread: M72x1backfocus: 27 ... Learn More
Model#: SE0086
Shelyak Instruments - QSIAdapter to mount a QSI ccd camera ('ws' front plate) on a Lhires III.thread: M42x0.75backfocus: 34 ... Learn More
Model#: SE0082
Shelyak Instruments - Old SX CCD adapter - CCD adapter for Lhires IIIThis adapter works for old Starlight Xpress models.thread: M42x1backfocus: 14 ... Learn More
Model#: SE0087
Shelyak Instruments - Standard Audine CCD Camera adapter
If you have an Audine with a Pentax shutter, look for the special adapter SE0013.... Learn MoreModel#: SE0011
Shelyak Instruments - QSI 516 or 532 (class 2) CCD Camera, large front plate (no filter wheel),with Canon EOS Lens - Based on Model, request a QuoteThis adapter works for the following models:-SBIG ST402-SBIG ST1603-Starlight Xpress SX (except H35/H36 or old models)-most Atik camerasthread: M42x0 ... Learn More
Model#: SE0014
Spectrography transforms how we look at our universe. Until recent years, this technology was limited to professional observatories with... astronomical budget!
Our passion to astronomy led us to design a complete and affordable line of spectrographs, from discovery to professional and scientifical practice - including educational solution which is important to us. You will also find with us state of the art off-the-shelf working solutions including key accessories such as guiding and acquisition cameras.
You will find in this web site technical details of our products but also a large documentary section with projects to run with your spectrograph from your backyard. We hope to help you in your first step in spectroscopy... and you second one!
In our design of those instruments (which we are also users), we follow some key principles :
- Simplicity and ease of use in the field.
- Scientifical: give you spectra to serve science.
- Technical quality of achieved results.
- Univeral, working with a wide range of standard equipment, even modest ones.
- Responsiveness to your needs.
- Instruments accessible to all...... and always the pleasure of observing and discovery !
Stars send us a light rich of information, let your instruments decode it. Applications are infinite, observing programs are extending in the scientifical community : you won't see the stars like before !


text:
Email to a Friend
Be the first to review this product
Sign up to get notified when this product is back in stock
Availability: Out of stock
Regular Price:
Special Price:
Double click on above image to view full picture
Use spaces to separate tags. Use single quotes (') for phrases.
You have no items in your shopping cart.
You have no items to compare.
Whats the sickest clothing brand in 2012?
Help Us to Keep Magento Healthy - Report All Bugs (ver. 18.104.22.168)