Building a Playstation Network Widget for Blog Engine

by Albert Mutangiri 6. March 2011 01:16

Well last week I spent a few hours digging into BlogEgine widgets, and I'm planning to add a few more custom widgets for my blog. BlogEngine.NET makes it very easy to create your own widgets. Widgets are ASP.NET Custom Controls. Each widget is in its own folder within the widgets folder found in your blog. All widgets must have a widget.ascx file and a widget.ascx.cs file. There are a few rules that you might need to adhere to for example the widget.ascx must override the WidgetBase Class, will look at that a bit later.

There is an API out there for playstation Network at codeplex.com that is exposed as a service. So all I needed was to consume this service and persist the xml feed with member information and game collection on a local store as well as provide a mechanism to check for latest updates and update this local feed.

So lets have a look at this service -- there is an operation that's exposed - GetProfile(), this requires your PSN ID and location and returns a collection of your games, trophies as well as your profile.



At runtime i lookup for updates on PSN Network and persist changes on a local store, this mechanism uses HttpRuntime.Cache to cache settings as well as the profile xml feed itself.

So there is two important controls you need (1) edit.ascx and (2) widget.ascx. The first one is for widget configurations, must inherit from the WidgetEditBase Class and override Save() function. So what are we interested in here ? We need to know the User PSN ID, Web Service URL, Refresh Interval for checking for updates on the server and total Number of trophies to diplay on the widget. We will use the key setting PLAY_STATION_NETWORK_KEY_SETTINGS to store these settings using the

HttpRuntime.Cache(PLAY_STATION_NETWORK_KEY_SETTINGS);


public partial class widgets_PSNetwork_edit : WidgetEditBase
{
    /* We will use this key setting to cache the current control settings */
    private const string PLAY_STATION_NETWORK_KEY_SETTINGS = "psn-network-settings";

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            StringDictionary settings = GetSettings();
            if (settings.ContainsKey("psn-id"))
            {
                txtPsnID.Text = settings["psn-id"];
                txtServiceURL.Text = settings["psn-service-url"];
                txtRefreshInterval.Text = settings["psn-feed-refresh-rate"];
                txtTotalNumberofTrophies.Text = settings["psn-total-trophies-per-page"];
            }
        }

    }
    /* Override the Save function of the WidgetEditBase Class with values supplied by the user from the UI */
    public override void Save()
    {
        try
        {
            StringDictionary settings = GetSettings();
            settings["psn-id"] = txtPsnID.Text.Trim();
            settings["psn-feed-refresh-rate"] = txtRefreshInterval.Text.Trim();
            settings["psn-total-trophies-per-page"] = txtTotalNumberofTrophies.Text;
            settings["psn-service-url"] = txtServiceURL.Text.Trim();
            SaveSettings(settings);
            HttpRuntime.Cache.Remove(PLAY_STATION_NETWORK_KEY_SETTINGS);
        }
        catch (Exception ex)
        {
            string msg = "Error Saving PSN Network Widget";
            if (ex != null) msg += " " + ex.Message;
            Utils.Log(msg);
        }
    }

}

The widget.ascx control is the actual widget that users will see on your blog and must inherit from the WidgetBase Class and override the following functions.

/* The Name of the Widget */
public override string Name { get; }
/* A boolean value that specifes if this widget is editable or not */
public override bool IsEditable { get; }
/*Renders the widget to the user. */
public override void LoadWidget() { }

To store the user profile i have a few internal classes to catter for this, I have the following Entities

1) PSNSettings - to store user preference settings for this widget.
2) TrophyCount - stores user trophies
3) PSNProfile - PSN user profile for example the progress, location etc.
4) PlayedGame - a collection of games as well as the related trophies.


The first time I load the widget, I check user settings from the cache and based on these settings we load the user profile on Playstation Network.
The constant value PLAY_STATION_NETWORK_REMOTE_OPERATION_NAME is the remote operation name on the web service to invoke.

private const string PLAY_STATION_NETWORK_REMOTE_OPERATION_NAME = "GetProfile";

/* the first time we load the widget, we check for the current settings */
public override void LoadWidget()
{   
        PSNSettings settings = getPSNSettings();
       /* logic to fetch user profile and game collection  here */
}
/* get user current widget settings */
private PSNSettings getPSNSettings()
    {
        Uri _networkserviceUri;
        int _refreshInterval = 10;
        int _totalNumberofTrophies = 4;

        PSNSettings psnsettings = HttpRuntime.Cache[PLAY_STATION_NETWORK_KEY_SETTINGS] as PSNSettings;
        if (psnsettings != null)
            return psnsettings;
        psnsettings = new PSNSettings();
        StringDictionary settings = GetSettings();

        if (settings.ContainsKey("psn-service-url") && !string.IsNullOrEmpty(settings["psn-service-url"]))
        {
            Uri.TryCreate(settings["psn-service-url"] + "/" + PLAY_STATION_NETWORK_REMOTE_OPERATION_NAME + "?psnid=" + settings["psn-id"] + "&location=", UriKind.Absolute, out _networkserviceUri);
            psnsettings.ServiceURL = _networkserviceUri;
        }
        if (settings.ContainsKey("psn-feed-refresh-rate") && !string.IsNullOrEmpty(settings["psn-feed-refresh-rate"]))
        {
            int temp_refreshInterval;
            if (int.TryParse(settings["psn-feed-refresh-rate"], out temp_refreshInterval))
            {
                if (temp_refreshInterval > 0)
                    _refreshInterval = temp_refreshInterval;
            }
        }
        if (settings.ContainsKey("psn-total-trophies-per-page") && !string.IsNullOrEmpty(settings["psn-total-trophies-per-page"]))
        {
            int temp_totalNumberofTrophies;
            if (int.TryParse(settings["psn-total-trophies-per-page"], out temp_totalNumberofTrophies))
            {
                if (temp_totalNumberofTrophies > 0)
                    _totalNumberofTrophies = temp_totalNumberofTrophies;
            }
        }
        psnsettings.RefreshInterval = _refreshInterval;
        psnsettings.TotalNumberofTrophies = _totalNumberofTrophies;
        HttpRuntime.Cache[PLAY_STATION_NETWORK_KEY_SETTINGS] = psnsettings;
        return psnsettings;
    }

The last two important functions take advantage of HttpWebRequest  to invoke the service, the nice part of this is that we dont need a pre-generated proxy stub to invoke the service. BeginGetPSNServiceRequest function accepts a uniform resource identifier, in this case the web service location + the operation name + parameters.


/* To Construct the URI, I call getPSNSettings() function */
 Uri.TryCreate(settings["psn-service-url"] + "/" + PLAY_STATION_NETWORK_REMOTE_OPERATION_NAME + "?psnid=" + settings["psn-id"] + "&location=", UriKind.Absolute, out _networkserviceUri); psnsettings.ServiceURL = _networkserviceUri;

/*Invokes the remote PSN Service and we pass a callback function EndGetPSNServiceResponse() to fetch the xml result */
private void BeginGetPSNServiceRequest(Uri url)
    {
        try
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            request.Credentials = CredentialCache.DefaultNetworkCredentials;
            request.BeginGetResponse(EndGetPSNServiceResponse, request);
        }
        catch (Exception ex)
        {
            string msg = "Error requesting PSN feed.";
            if (ex != null) msg += " " + ex.Message;
            Utils.Log(msg);
        }
    }
   /* loads the response into an xml document and then we persist this to our local store using the XmlDocument.Save() function */
    private void EndGetPSNServiceResponse(IAsyncResult result)
    {
        try
        {
            HttpWebRequest request = (HttpWebRequest)result.AsyncState;
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(response.GetResponseStream());
                HttpRuntime.Cache[PLAY_STATION_NETWORK_KEY_SETTINGS] = doc.OuterXml;
                SavePSNFeed(doc);
            }
        }
        catch (Exception ex)
        {
            string msg = "Error retrieving PSN feed.";
            if (ex != null) msg += " " + ex.Message;
            Utils.Log(msg);
        }

    }

The widget is a very simple ASP.NET ListView Control bound to the PSNProfile class. The installation is very easy. Just extract the package to widgets folder and login as admin user to add this widget to widget zone, edit settings and that's all. A good example is on the right side of my blog.

Download widget source below.
PSNetwork.zip (16.87 kb)

Tags:

Finally got myself Move motion controller for my PS3

by Albert Mutangiri 30. September 2010 02:33

Yae, after a long wait and finally it's here, so i thought i must  hook myself up. It's really an amaizing gaming experince, virtual reality motion sensing - New generation video game accessory.

The PlayStation Move starter pack contains the two key elements of PlayStation Move: The PlayStation Eye and the PlayStation Move Motion controller. Containing sophisticated motion sensing technology, the Move Motion controller gives you an accurate and reliable experience complete with vibration feedback and a dynamic colour changing sphere.

The PlayStation Eye completes the experience by tracking the sphere on top of the Move Motion controller, making it that much more accurate. Not only that, but some games will use the camera to put you in the game "Yae you better be...."
Whether it's taking aim in The Shoot: Move, beating people down in The Fight

 

Lights Out or getting everyone involved in Start the Party: Move you can rest assured that every one can get to grips with PlayStation Move...

Tags:

Gaming

Hooking up PS3 to a windows media server

by Albert Mutangiri 14. September 2010 06:59

Been battling lately to configure PS3 media server on my home network. I tried this PS3 media server with no luck, i could see the folder structure on my playstation console, but just couldnt just open the media files.

With Windows Media Player 11 which is included with Microsoft Windows 7 and available as an update or download for Windows XP has the ability to perform as a media server .
Great news on that is that since Microsoft is a board member of the DLNA, the media server can function as a DLNA media server. DLNA (Digital Living Network Alliance) is a standard that
enables digital devices such as personal computers, digital video recorders, and TVs to be connected on a network and to share data that is on other connected, DLNA-compatible devices.
DLNA-compatible devices serve two different functions.

"Servers" distribute media such as image, music, or video files, and "clients" receive and play the media. Some devices perform both functions.


Using a PS3™ system as a client, you can display images, or play music or video files that are stored on a device with DLNA Media Server functionality over a network


DLNA media servers can be connected to from a number of devices, most importantly to me right now of course is the ability for it to be connected to via your Playstation 3.

I'm running Windows 7 professional at home, all i had to do is to configure media sharing via media player by simply
opening your Microsoft Media Player 11.

Click on Library --> Media Sharing to configure your computer for DLNA media sharing.


On my LAN, i have a wireless router, and Adsl modem for internet connection.
Enabling the DLNA Media Server function of the connected device will make it's content available for shared access..

 

Now i can browse though my music collection, watch movies and or even organize photos on playstation as long as i'm connected to my LAN, and it's that simple...

 

Tags:

Playstation 3

Are you a ‘good’ programmer? I’m not! - Software Engineer

by Albert Mutangiri 6. May 2010 17:46

I was just checking Prof Barry Dwolatzky's topic this week and i just found it so interesting, I mean seriously " Are you a good programmer? ".Well i would look at three different things that really matters most.

1) Passion
In my corporate experience, I met a kind of technical guy I’d never met before: the career programmer. This is a person who’s doing IT because they think it’s a good career. They don’t do any programming in their spare time. They’re shocked when they find out I have a LAN and an awesome computer setup at home. They just do it at work. They don’t learn new stuff unless sent on a training program (or motivated by the need to get a job that requires that technology). They do “programming” as a day job. They don’t really want to talk about it outside of work. When they do, they talk with a distinctive lack of enthusiasm. Basically, they lack passion.

2) Self-teaching and love of learning
Programming is the ultimate moving target. Not a year goes by without some new technology robbing an old, established standard blind and changing half the development universe. This is not to say that all good programmers pick up these changes and ride the bleeding edge. However, there’s a class of programmers that will never, ever pick up a new technology unless forced to, because they don’t like learning new stuff. These programmers will typically have learnt programming at university, and expect to get by on whatever skills they picked up there, plus whatever courses their company is willing to send them on.

3) Hidden experience
This is correlated with the “Passion” point, but it is such a strong indicator that I’d like to emphasise it with its own point.
I started programming when I was about 17, with vb6, c++ & java then migrated to the .net framework, did some php. When I was 23 I wrote an enterprise application for financial instituation - online money transfer . This was what I call my “coccoon stage”. When I entered that stage, I was a mediocre programmer, and lacked the confidence to do anything really complicated. When I finished it, I had gained that confidence. I knew that I could code pretty much anything so long as I put my mind to it.

Has that ever appeared on my CV? Nope.
I strongly believe that most good programmers will have a hidden iceberg.

Tags:

Mail database objects - via sql

by Albert Mutangiri 26. April 2010 20:54

Last month I had a complex task working with one of my friend's legacy applications. He's got a bunch of sql data transformation services configured to import data from a bunch of text files. Although data transformation services offers powerfull capabilities when dealing with bulk data imports, They are pretty complex to debug as well. So we needed a way to track the number of records that are imported and errors if any for each DTS as well as notify the administrator with this data.

So well I figured out that with Data Transformation Services, you can configure it to log it's activities in msdb system database - by default it creates logs in sysdtspackagelog table. We needed to send a view of this package log in html format - via email to the configured Administrator after each dts completes running.

With the help of the system procedure msdb.dbo.sp_send_dbmail, I've created a custom mail sender in sql which we could execute by passing parameters to it and run it in the context of DTS running as a custom sql script, it loops through the column names of the specified database object and generates html. Well this worked like a charm Smile


create proc [dbo].[send_sql_table_as_html] 
 
    @source_db    sysname,       --where the @object_name is residing
    @schema       sysname,        --Schema name eg.. dbo.
    @object_name  sysname,      --Table or view to email
    @emailAddres varchar(75),   --Mail Address
    @name nvarchar(15),         --Package Name
    @order_clause nvarchar(max)  --The order by clause eg. x, y, z
as
begin  
  declare @subject nvarchar(max),@body    nvarchar(max)

--Get columns for table headers..
exec( '
    declare col_cur cursor for
    select name
    from '
+ @source_db + '.sys.columns
    where object_id = object_id( '
'' + @source_db + '.' + @schema + '.' + @object_name + ''')
    order by column_id
    '
)

    open col_cur
    declare @col_name sysname
    declare @col_list nvarchar(max)
    fetch next from col_cur into @col_name
    set @body = N'<table border=1 cellpadding=1 cellspacing=1><tr>'
    while @@fetch_status = 0
        begin
              set @body = cast( @body as nvarchar(max) )
                      + N'<th>' + @col_name + '</th>'
              set @col_list = coalesce( @col_list + ',', '' ) + ' td = ' + cast( @col_name as nvarchar(max) ) + ', '''''
              fetch next from col_cur into @col_name
        end
        deallocate col_cur
    set @body = cast( @body as nvarchar(max) )

              + '</tr>'
    declare @query_result nvarchar(max)
    declare @nsql nvarchar(max)

    --Form the query, use XML PATH to get the HTML
    set @nsql = '
        select @qr =
               cast( ( select '
+ cast( @col_list as nvarchar(max) )+ '
                       from '
+ @source_db + '.' + @schema + '.' + '.' + @object_name +'
                       order by '
+ @order_clause + '
                       for xml path( '
'tr'' ),type
                       ) as nvarchar(max) )'

 
    exec sp_executesql @nsql, N'@qr nvarchar(max) output', @query_result output
    set @body = cast( @body as nvarchar(max) )  + @query_result
   --Send notification
    set @subject = 'Please find the upload details for ' + @name + ' file '
    set @body = @body + cast( '</table>' as nvarchar(max) )

    set @body = '<p>File upload Details for -------' + @name + ' file'
              + ' </p>'
              + cast( @body as nvarchar(max) )

   EXEC msdb.dbo.sp_send_dbmail  @profile_name = 'Test',  --Profile configured in sql, this will be used by sp_send_dbmail to send mail

                                  @recipients = @emailAddres,
                                  @body = @body,
                                  @body_format = 'HTML',
                                  @subject = @subject

end

Tags: ,

Sql legacy - DTS

Calendar Theme Customization

by Albert Mutangiri 22. April 2010 18:27

As part of my blog theme customization , I thought i must share this tip for your blog entry calendar theme as well. So rather displaying  date strings, why not render these date strings in a nicely done calendar thumbanil display using css. All we need is a bunch of images - in this case we have 12 months in a year, so we will have 12 images - one calendar thumbnail per month. We will need to name these images in a sequence like below


We will define three important style definitions.


/* This style will define the positioning of the calendar thumbnails */
.calendar
{
    float: right;
    margin-right: 6px;
    width: 42px;
    height: 42px;
}
/* this style defines daily text rendering */
.calendar-day
{
    font-weight: bold;
    font-size: 1.3em;
    color: #000;
    width: 42px;
    text-align: center;
    padding-top: 14px;
}
/* this style defines monthly thumbnail rendering, we will decide using this style at runtime which thumbnail to display - we will have 12 of these below defined for all 12 thumbanils */
#content .calendar-icon-01
{
  background: url('calendar/01.gif');
}
#content .calendar-icon-02
{
    background: url('calendar/02.gif');
}

Blog Engine themes ships with two default controls - CommentView.ascx and PostView.ascx, In this case we're interested with the PostView.ascx for customization. Once we've defined our css and created our thumbnails, in our PostView control depending on datetime month of the year we can decide at runtime which style to apply to the calendar div.

<div class="<%="calendar calendar-icon-0" + Post.DateCreated.Month.ToString() %>"><div class="calendar-day">               <%=Post.DateCreated.Day.ToString() %></div></div>

So this will diplay a custom thumbnail for each month. Download Source Calendar-theme.rar (32.59 kb)

Tags:

BlogEngine.NET

.Net Reflactor - With Addon right in your IDE

by Albert Mutangiri 8. April 2010 19:21

This is pretty handy,  right in your IDE Wink . Integrates the power of .NET Reflector into Visual Studio, Decompile third-party assemblies from within Visual Studio. Step through decompiled assemblies and use all the debugging techniques you would use on your own code. Download the trial version here

 

Tags:

Essential Developer Tools

Modal Popup in a ListView

by Albert Mutangiri 5. April 2010 03:37

In this Demo i will explain how one can take advantage of the asp.net ajax modal popup extender to diplay related data in master detail format. With the help of Asp.net Ajax Controltoolkit, this toolkit offers some of the most powerfull extenders that can be easily pluged into your project and take advantage of ajax capabilities without chaining lots of code. Download the ControlToolkit here

I've created an empty website. In this project i've added a LINQ to SQL data model to the Northwind Customers and Orders tables. This is a default example database that's installed when you install sql server, if you don't have it, you can alternatevely download it here. Our main objective is to display customer details in a listview and drill down to the orders for a specific customer. I will use two user controls - customer.ascx and customerorders.ascx and one default.aspx file.

I have also created a custom database helper class that allows us to do the usual Create, Update, Delete tasks. In this Helper class, I have static functions addNewEntity for example - Is a generic function that takes advantage of the powerfull generic C# constructs where one can pass parameters to types - addNewEntit<T> accepts a type and that type is of class type - as represented by the contraint - where T: class. In this case NorthwindDataContext allows us to query our LINQ to SQL data model.

public static NorthwindDataContext getEntityContext(){
        return  new NorthwindDataContext(ConfigurationManager.ConnectionStrings[1].ToString());
    }
    public static void addNewEntity<T>(T obj) where T: class
    {
        using (var db = getEntityContext())  
        {
            db.GetTable<T>().InsertOnSubmit(obj);
            db.SubmitChanges();
        }
    }

In the customers user control i've added a listview control with two templates - layout template and item template. A listView control is one of the most flexible controls when it comes to displaying tabulated data , it's like a datagrid on steroids. You can define how you want your listview to be rendered by manipulating a bunch of templates that ships with this control. In this case i have only two template fields - one is for defining how many columns we're going to display and the other one defines the Items to be bound to this control.

In the customers user control, we bind the list of customers, in this case by using LINQ to SQL, we're actually dealing with an enumerable list of customers. This raises the level of abstraction for data programming, thus helping to eliminate the impedance mismatch between data models and between languages that application developers would otherwise have to deal with. Eliminates all the plumbing work associated with casting types to appropriate data types,  and the code is pretty much easy to understand, I mean this easy to understand  =>

using (var context = DatabaseHelper.getEntityContext())
   {
                var customers = context.Customers.ToList();
                if (customers.Count > 0)
                {
                    lvCustomers.DataSource = customers;
                    lvCustomers.DataBind();
                }               
   }

We will add reference to the controltoolkit both user controls.


<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>


In the customers user control we will add a panel and set its visibility to false, this will be the target control for the modal popup extender control, This panel will host our custom user control - customer order details and note a hidden button as well - this will be used by this extender as a TargetControl. Css Popupbody is applied to the panel and the ModalBackground is for the popup extender.


<asp:Panel ID="pnlOrderDetail" runat="server" CssClass="PopupBody" Width="750px"  Style="display: none">       <uc1:customerorders ID="customerorders1" runat="server" />   </asp:Panel> <asp:Button ID="btnOrderDetail" runat="server" Style="display: none" /><ajaxToolkit:ModalPopupExtender ID="mdlOrderDetailView" runat="server" TargetControlID="btnOrderDetail"    PopupControlID="pnlOrderDetail" BackgroundCssClass="modalBackground" />

To open the popup extender we need to fire its show() Method, In this case we will do this on the ListView Item_Commad Event. User Controls in asp.net can fire events that can be handled by the host page or another user control as well. In this demo, our modal popup control will fire events on paging as well as on deleting an item in the list so that we keep the popup open, and only close it when needed.


/*  Events defined in the popup control for customer order details */
    public event EventHandler evtClosePopup;
    public event EventHandler evtKeepPopOpen;
    public event EventHandler evtDeleteItem;


/* The customers control handles events fired by customer orderdetails user control.*/
    customerorders1.evtClosePopup += new EventHandler(customerorders1_evtClosePopup);
    customerorders1.evtKeepPopOpen += new EventHandler(customerorders1_evtKeepPopOpen);
    customerorders1.evtDeleteItem += new EventHandler(customerorders1_evtDeleteItem);


/* to show the popup control we will call the mdlOrderDetailView.Show() method */
protected void lvCustomers_ItemCommand(object sender, ListViewCommandEventArgs e)
{
   switch (e.CommandName)
    {
            case "ViewOrderDetails":
                var customerId = e.Item.FindControl("lblCustomerID") as Label;
                customerorders1.customerID = customerId.Text;
                customerorders1.setCustomerOrderDetail();
                mdlOrderDetailView.Show();
                 break;   

    }
}


And the final result, You can download source files on this link ListViewSample.rar (356.16 kb)


Tags: , , , ,

ASP.NET | C# | LINQ

MVC vs ASP.NET Webforms

by Albert Mutangiri 3. April 2010 03:32

I've been coding asp.net web apps using web forms for so long now, I mean since the early releases of .net framework and to be straight to the point webforms rock! Although this doesn't sound revolutionary, the fact that asp.net webforms makes building web applications quite handy by abstracting the complexities when dealing with things like application state, does this really mean we're all going to dump webforms for MVC??

Yes MVC is pretty sexy, it's a fix to the issues we have with web forms - refering to bloated ViewState and it's pesky postback model, so what happens when one needs an application state mechanism? Are we going to re-invent the weel? I really don't see the idea, this goes down to the idea of choosing the right technology for the right job.

Tags:

ASP.NET

PS3 - Motion-sensing controller

by Albert Mutangiri 1. April 2010 17:56

Sony has unveiled a hotly anticipated motion-sensing controller that it hopes will fuel new interest in its PlayStation 3 videogame consoles.

PlayStation Move wands will hit the market in time for the year-end holiday shopping season and aim to tap into a zest for motion-sensing controls that made Nintendo Wii consoles marketplace superstars. We've been waiting for this for years now, I like to think this is the next generation of motion gaming. Microsoft is yet to release its own controller free gaming and entertainment experience - code named Natal - it enables users to control and interact with the Xbox 360 without the need to touch. I would love to put my hands on this, the only boring thing is that this might take time to get to the South African Market.

 

 

Tags:

Playstation 3

About Me

Hi, My name is Albert Mutangiri, I am a software developer currently interested in software integration, .net technologies and Java. I work for softwareag where I'm currently developing enterprise applications for business process automation using Java Technologies.

PSNetwork


bertoncaffeine

Playing
17 0 1 0 18
13 6 0 0 19
4 0 0 0 4
22 1 0 0 23
0 0 3 0 3