Friday, October 28, 2011

Microsoft Lync 2010 No Audio without Microphone Fail

PROBLEM: In Microsoft Lync 2010, you cannot listen in a web meeting if you don't have a microphone plugged in. It would make sense that you could at least listen in a web meeting (e.g. someone is presenting and you just want to listen) and if you need to provide feedback you can just type a question. But alas that isn't supported (fail) - it's a bug, and Microsoft has said they won't be changing their product (fail fail).

Microsoft has already documented this as a bug with no comments on if it will ever be repaired.

This means that audio cannot be received by a participant in a Lync Server Online Meeting unless the participant has a microphone plugged in.

I was asked by the MS support tech (who was as helpful and polite as he could be) to submit a BIS (Business Impact Statement). Hopefully the BIS will be viewed as worthy of getting the developers to repair this problem.

I'm surprised that I had to go this far to find an answer if not a solution. Is it really that odd for a typical training to be held using Lync/OCS or do most companies install a microphone or webcam on every PC?
Unfortunately the response that fellow got was:
Microsoft just sent me an update:

"During our review we noticed that the Microphone parameter is intertwined to the nerve center of the MCUs.

Making a change would involve too many components and the high cost associated for making these changes would not justified to qualify it as a Cumulative Update within this product release lifecycle.

Unfortunately, the bug that has been filed for this case has been rejected."

He goes on to recommend buying a few hundred microphones from Amazon.

Insane.
The only workaround talked about is:
As far as I can tell, the software is satisfied as long as you plug anything into the microphone jack (even a disconnected plug from an old headset worked for me), though you can't unplug it afterwards without the call getting interrupted (so multiple people can't share the same plug).
Someone else tried this:
I found that out and ended up buying 500 audio adapters for less than a quarter each. Explaining over and over to people why they have to be plugged in was pretty humiliating. I tested about 20 machines and found 2 that had sound cards/sound card drivers smart enough to recognize that the adapters weren't microphones. I'll have to get them real mics.

I haven't yet tried to find out what happens with outside callers using web app. I have a good guess as to what the results will be...

MS recognizes this is a bug, and decided to fix it it CU4, but then decided not to. The only thing I can come up with for that is the recent purchase of Skype. Maybe the more difficult repairs will be delayed/cancelled while Skype is being integrated into the next version of Lync? I really don't have any idea if that's the plan or not - I'm just speculating.
SOLUTION: So the alternatives are:

1. Get headphones with a microphone built in; or
2. Plug anything into the microphone plug; or
3. Watch a recorded webinar afterwards (rather than participate live); or
4. Use a different product (e.g. Skype).

If you can figure out where to log this as a problem with MS and can be bothered that would be great. I think we'll just go with option 1 for those who require it. Overall, sorry MSFT but this is a fail.

Thursday, October 27, 2011

Facebook Graph API and redirect_uri and QueryString parameters

PROBLEM: If you are using the Facebook API e.g. to do the login for your website etc (http://developers.facebook.com/docs/authentication/), you may find yourself wanting to get the user to login to Facebook but then return to the page they came from. My first reaction was to add the URL they came from to the end of the redirect_uri querystring parameter e.g.

https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL?orig_url=http://example.com/default.aspx

Of course you would url encode the orig_url parameter and then decode it when you wanted to use it... it actually does work for the above type of call... but when calling the app authentication api it doesn't like it. Base64 encoding it doesn't work either. And remember, a little known fact is that the redirect_uri needs to be the same for when you are doing the app authorization as the app authentication (see below url)

https://graph.facebook.com/oauth/access_token?client_id=YOUR_APP_ID&redirect_uri
=YOUR_URL?orig_url=http://example.com/default.aspx&client_secret=YOUR_APP_SECRET&code=THE_CODE_FROM_ABOVE

Bottom line is that I tried the above approaches and kept getting a HTTP 400 error "Error validating verification code.".

SOLUTION: Taking a step back, rather than try and get what should work working, try a different approach. In my case, simply put the original URL into a session variable for use later on (http://stackoverflow.com/questions/5747320/how-to-encode-the-redirect-uri-for-facebook-login).

e.g.

Session["UrlToReturnToAfterLogin"] = HttpContext.Current.Request.Url.OriginalString;

Too easy.

Tuesday, October 18, 2011

Add the optgroup tag to your DropDownList

Problem: The asp.net DropDownList control does not support rendering of the optgroup tag (it will only generate option tags).

Solution: Once again, a bit like trying to get the validation controls to use the display:block style when its display is set to dynamic, sometimes it can be tough to bend asp.net to do what you want when it isn't supported out of the box.


Your options seem to be:

1. Use an adapter to change the html that the asp.net DropDownList control renders (affects all DropDownLists in your solution).
2. Inherit from the DropDownList and change the html that your new control renders.
3. Use javascript to do some magic once the control has rendered.
4. Don't use optgroup - depending on your scenario, it may not be the best UI solution.

I went with option 1. and a lot of trial and error based on various examples on the net. My main problem was that there weren't enough complete code solutions showing all the bits of code and how to use it.

The examples I tried from the stackoverflow page ended up giving me the following error when I tried submitting the page:

Invalid postback or callback argument. Event validation is enabled using ...
I didn't have time to investigate so I went with a different example. In the end the best example I found came from Christoff Truter: http://www.cstruter.com/blog/259. The only clarifications: Step 3 should all be within:
public class DropDownListAdapter : WebControlAdapter
{
...
}
In the overridden version of OnLoad in Step 3, you need to add a null check before setting the Group attribute value (in case you have provided a listelement in your dropdownlist without the "Group" attribute e.g. a blank 'please select a value' item). i.e.
if (groups[i] != null)
{
dropDownList.Items[i].Attributes["Group"] = groups[i].ToString();
}
The final piece of the puzzle was how to create your DropDownList. The big gotcha was that I couldn't use DataSource/DataBind because when I did I lost the attribute that I had set on the listitems (perhaps it was because of the issue described here: http://www.4guysfromrolla.com/articles/091405-1.aspx). This was my code (if you have a way to get DataSource/DataBind working let me know).

protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//Find all currently open clubs which have indicated that they provide X-Service
List currentXServiceClubs = DBHelper.GetAllCurrentClubsOfferingXService();

//Create list with the custom "Group" attribute
List listItemsForCurrentXServiceClubs = new List();

lstXServiceClubs.Items.Add("");
foreach (var club in currentXServiceClubs)
{
ListItem newListItem = new ListItem();
newListItem.Attributes.Add("Group", club.State);
newListItem.Text = club.CentreName;
newListItem.Value = club.CentreID.ToString();
lstXServiceClubs.Items.Add(newListItem);
//NOTE: If you use the DataSource / DataBind notation then
//the custom attribute will not be passed through to the DropDownListAdapter
//and hence you will lose the OptGroup functionality. As a future project
//review if there is a way around this.
}
}
}



ASP.NET Validation Controls and Styles

PROBLEM: RequiredFieldValidator with Display="Dynamic" places display:inline on the error text when displayed (and I want it to be display:block)

SOLUTION: Well there is no elegant solution! Sometimes the rapid development tools that are normally so helpful in .net just aren't flexible enough to allow what you want to do. The issue is discussed here: http://www.stackoverflow.com/questions/2243498.

Essentially when the validator is first displayed it sets (via .net generated javascript) style="display:none" on the span tag. This element then gets switched from "none" to "inline" when there is an error to display.

Your options?

1. Modify the automatic asp.net javascript - not nice, and could possibly break after future upgrades or browser changes etc. - but probably your best bet if you are desperate - here is how: http://caliberwebgroup.blogspot.com/2009/02/overriding-javascript-in-webresourceaxd.html

2. Roll your own validation controls - possible but then you lose all the default out of the box goodness that come with the asp.net validator controls.

3. Live with it. I went with this option. Sometimes 95% is good enough.

Thursday, October 13, 2011

ASP.NET code in app_code files compile but "Go to definition" doesn't work

PROBLEM: Created some class files in the App_Code folder of an asp.net web application - compiled and there were no errors, but "Go to definition" (F12) wasn't working on some of the classes etc.

SOLUTION: Really easy solution for a beginner's problem - ensure the "Build Action" property of your classes is set to "Compile", not "Content" (it might have defaulted to "Content" because it was a web application not a website (I was just following the App_Code folder name as a convention)).

Wednesday, October 12, 2011

Firefox no likey innerText

PROBLEM: You've gotten your hands dirty on some client side coding a.k.a. javascript, and its working fine in all browsers like IE and Chrome but not in Firefox. The offending line is something like:

" var iCurrent = parseInt(document.getElementById('" + lblWordCount.ClientID + "').innerText);" +
SOLUTION: Use innerHTML instead of innerText e.g.

//Note: Don't use innerText as it isn't supported by Firefox
" var iCurrent = parseInt(document.getElementById('" + lblWordCount.ClientID + "').innerHTML);" +

CAVEATS: Ok, so after a bit more googling (http://stackoverflow.com/questions/1359469/innertext-works-in-ie-but-not-in-firefox) it's definitely not the preferred solution and has issues itself, but for my simple scenario it worked ok. Ideally I should probably be using some jquery or accessing the DOM properly etc. I'm open to here better solutions.

Panel visible=true has no effect

PROBLEM: I have a Panel that I'm setting visible=true explicitly. The debugger passes over that line and visible still evaluates to False on the next line. Obviously as a result, the Panel is not shown. How is this possible?

SOLUTION: Ensure the panel is not nested inside another panel or any other type of container which has Visible set to false e.g. if you are going through some code to make some panels visible/invisible, then make sure you've first set the parent panel to visible=true (if relevant).

Exact same problem and solution was discussed on Stack Overflow http://stackoverflow.com/questions/2539204/panel-visible-true-has-no-effect