Click here to Skip to main content
Click here to Skip to main content

Webpart/Portlet development in ASP.NET MVC Framework

By , 31 Aug 2012
 

webpartsMVC/VideoImage.jpg
Portal Video

Application's Live Demo 

Table of Contents  

Introduction

As an MVC Framework admirer, I had gone through high and low for Portlet or Webpart solution in ASP.NET MVC, but search didn't come up with desirable solution. This development effort is made to materialize Portlet/Webpart application in ASP.NET MVC Framework. It's indented to provide accumulated view with segregation, and offers personalization features. It's intended to be as concise as possible to focus most on idea, therefore ASP.NET session and application variable shall be our repository, therefore customed or personalized Portlet/Webpart adjustment shall not withstand for multiple ASP.NET Session.

Pre-requisites

In order to follow this article, you need to have some understanding of MVC Framework. If you think you have sufficient expertise, then you are best to further read through this article.

If you still have not setup ASP.NET MVC, please have the items listed below installed before proceeding any further. You can also install ASP.NET MVC using Microsoft Web Platform Installer too.

Data Model

First to begin with, understanding data model is pivotal. Its entity describes the way the Portlet/Webpart would be harmonized into Portal.

webpartsMVC/Data_Model.JPG
Category Entity

It holds categories data, to segregate Portlet/Webpart into categories. Entity has one-many relationship with Portlet and Portlet_User entities. Entity would be habitated with data on start application event and resides in ASP.NET application variable.

Portlet Entity

It is a child of Category entity, has one-many relationship with Portlet_User entity. It holds default Portlet/Webpart information, regarding their placement on portal.

  • Portlet_ID: It's an entity's primary key, used to specify portlet.

  • Category_ID: It's hold category ID which demonstrates which category Portlet/Webpart belongs to

  • Link: It holds link to RSS Feed

  • Column_No: Describes column number or webpart zone for the Portlet/Webpart.

  • Title: Holds RSS Feed title

  • Row Sequence: Holds row number in a particular column

Portlet User Entity

It's a child of Category, Portlet and User entity. It's more or less a replica of Portlet entity. It holds default Portlet/Webpart information, regarding their placement on portal, and habitated at ASP.NET Session start up event. All customization and personalization would be done in this Entity.

Generate Portal View

It comprises several levels of abstraction through ASP.NET usercontrols. Each userControl performs its specific contribution to have overall view.

webpartsMVC/Portal_Loading.jpg

webpartsMVC/Portal_Loaded.jpg

webpartsMVC/collapse.jpg

Portal (Portal.aspx)

It's portal's entry point, and initiates the first level of abstraction, it renders partial view TabPage.asmx.

Tab Page (TabPage.ascx)

It's a first level abstraction. It generates tabpages for individual category which then segregates portlets to their respective tabs. Each Tab constitutes column or webpart zone, here Tab has come up with three columns which are portletColumn1XX first column or left zone, portletColumn2XX for second column or middle zone and portletColumn3XX for third column or right zone. Where XX would be substituted with context category ID. They decide which category the portlet should reside and in which column. Hence portlet placement decision is made at this level.

  <% 
        System.Data.DataRow[] rows = ((WebApplication.Models.ds)Application
		["data"]).Category.Select();
        System.Data.DataRow[] piRows = rows;
        int total_Category_Protlets = 0;
        string status_Filter = " Is_Active = " + 
		ViewData["is_Active_Portlets"].ToString();
        int total_Portlets = ((WebApplication.Models.ds)
	Session["data"]).Portlet_User.Select(status_Filter).Length;
        string funct_Name = "";
        string status = "";
        if (Convert.ToBoolean(ViewData["is_Active_Portlets"]))
            status = " Active ";
        else
            status = " Disable ";
    %>
    
    <%-- application pagetabs are generation  --%>

<div id="tabs" style="MIN-HEIGHT: 500px; HEIGHT: 100%"> 
    <strong style="COLOR: black">Total : </strong><em id="currentActivePortlets" 
	style="COLOR: black">
	<%= total_Portlets.ToString()%></em>  <strong style="COLOR: black">
	<%= status %> RSS Feeds</strong>    

<ul>
        <% foreach (System.Data.DataRow row in rows)
           {  %>  
            <% total_Category_Protlets = 
		((WebApplication.Models.ds)Session["data"]).Portlet_User.Select
		( status_Filter + " and Category_ID = " + 
		row["Category_ID"].ToString()).Length; %>          

<li><a id="<%= "tab" + row["Category_ID"].ToString() %>" 
	href="%3C%=%20%22#tabs-%22%20+%20row[%22Category_ID%22].ToString%28%29%20%%3E">
                    <%= row["Category"].ToString() + " 
		( " + total_Category_Protlets.ToString() + " ) "%></a> 
	    <%} %>
    
</li>
</ul>
    
    <%-- application pagetabs contents generation that is portlets/webpart   --%>
	<% foreach (System.Data.DataRow catRow in rows)
    {  %>  
        <% funct_Name = "catRadButton" + catRow["Category_ID"].ToString(); %>
        <script type="text/javascript">
	        function <%= funct_Name %>() {
	            
	            if( $('<%= "#radio1-" + catRow["Category_ID"].ToString() %>').
			is(':checked') )
	            {
	                $('<%= "#" + "tabs-" + catRow
			["Category_ID"].ToString() %>' ).find(".portlet").find
			(".portlet-content").toggle(true);
	                $('<%= "#" + "tabs-" + catRow
			["Category_ID"].ToString() %>' ).find(".portlet-header 
			.ui-icon-plusthick").toggleClass("ui-icon-minusthick").
			toggleClass("ui-icon-plusthick");
	           	                
	            }
	            else
	            if( $('<%= "#radio2-" + catRow["Category_ID"].ToString() %>').
			is(':checked') )
	            {
	                $('<%= "#" + "tabs-" + catRow["Category_ID"].ToString() %>' ).
			find(".portlet").find(".portlet-content").toggle(false);
	                $('<%= "#" + "tabs-" + catRow["Category_ID"].ToString() %>' ).
			find(".portlet-header .ui-icon-minusthick").toggleClass
			("ui-icon-minusthick").toggleClass("ui-icon-plusthick");
			    }
	            else
	            if( $('<%= "#radio3-" + catRow["Category_ID"].ToString() %>').is
			(':checked') )
	            {
	                
	            }
            }
	    </script>
        

<div id="<%= "tabs-" + catRow["Category_ID"].ToString() %>" style="WIDTH: 100px"> 
        
                <%-- intializing tabpage first column --%>
                
           
                <%-- intializing tabpage second column --%>
                
		   	    
		   	    <%-- intializing tabpage third column --%>
                

<table width="300">
<tbody>
<tr>
<td colspan="3"><input önclick="<%=" funct_name="" %="" type="radio">() 
id="<%= "radio1-" + catRow["Category_ID"].ToString() %>" 
name='<%= "cat-" + catRow["Category_ID"].ToString() %>' />
<label for="<%= "#radio1-" + catRow["Category_ID"].ToString() %>" 
style="color: rgb(92, 135, 178);">Expand</label> 
<input önclick="<%=" funct_name="" %="" type="radio">() 
id="<%= "radio2-" + catRow["Category_ID"].ToString() %>" 
name='<%= "cat-" + catRow["Category_ID"].ToString() %>' />
<label for="<%= "#radio2-" + catRow["Category_ID"].ToString() %>" 
style="color: rgb(92, 135, 178);">Collapse</label> 
<input önclick="<%=" funct_name="" %="" type="radio">() 
id="<%= "radio3-" + catRow["Category_ID"].ToString() %>" 
name='<%= "cat-" + catRow["Category_ID"].ToString() %>' checked=checked />
<label for="<%= "#radio3-" + catRow["Category_ID"].ToString() %>" s
tyle="color: rgb(92, 135, 178);">None</label> </td>
</tr>

<tr>
<td valign="top" style="WIDTH: 100px; VERTICAL-ALIGN: 100%">
<%-- intializing value for portlet/webpart that would passed to partial view as 
parameter for further assesment --%> <% ViewDataDictionary vdd = new ViewDataDictionary(); 
vdd["category_ID"] = catRow["Category_ID"].ToString(); %> 
<%-- first columns pagetabs portlets/webpart generation --%>s</td>

<td valign="top" style="WIDTH: 150px">
<%-- second columns pagetabs portlets/webpart generation --%> 
<div class="column" id="<%= "portletColumn2" + catRow["Category_ID"].ToString() %>" 
style="WIDTH: 285px; FONT-SIZE: 1.2em">
<% piRows = ((WebApplication.Models.ds)Session["data"]).Portlet_User.Select
(status_Filter + " and Category_ID = " + catRow["Category_ID"].ToString() + 
" and Column_No = 2 ", " Row_Sequence asc "); 
foreach (System.Data.DataRow piRow in piRows) 
{ vdd["Portlet_ID"] = Convert.ToInt32(piRow["Portlet_ID"]); 
vdd["Title"] = piRow["Title"].ToString(); Html.RenderPartial("Portlet", vdd); } %> </div>
</td>

<td valign="top" style="WIDTH: 150px">
<%-- second columns pagetabs portlets/webpart generation --%> 
<div class="column" id="<%= "portletColumn3" + 
catRow["Category_ID"].ToString() %>" style="WIDTH: 285px; FONT-SIZE: 1.2em">
<% piRows = ((WebApplication.Models.ds)Session["data"]).Portlet_User.Select
(status_Filter + " and Category_ID = " + catRow["Category_ID"].ToString() + 
" and Column_No = 3 ", " Row_Sequence asc "); 
foreach (System.Data.DataRow piRow in piRows) 
{ vdd["Portlet_ID"] = Convert.ToInt32(piRow["Portlet_ID"]); 
vdd["Title"] = piRow["Title"].ToString(); Html.RenderPartial("Portlet", vdd); } %> </div>
</td>
</tr>
</tbody>
</table>


	    </div>

 
  	<%} %>
</div>

Portlet (Portlet.ascx)

It's a second level abstraction and rendered only from TabPage.ascx control, it defines Portlet/Webpart frame in which its content needs to reside. It depends on next level abstraction, and relies on AJAX call to portlet controller's content controller method which will flush content inside portlet frame.

 
     <% 

    string portlet_ID = Convert.ToInt32(ViewData["portlet_ID"]).ToString().Trim();
    string portletName = "portlet" + portlet_ID;
    string portletFunc = "func" + portletName;
    string portletContent = "portlet" + portlet_ID + "Content";
    %>

    <script type="text/javascript">
        function <%= portletFunc + "_" %>() {
            <%= portletFunc %>("1");
        }
        
        function <%= portletFunc %>(page) {
        if( page == 1 )
        {
            $('#<%= portletContent %>').html('');
        }
        else
        {
            $('#<%= portletContent %>').html
		('<img alt="Loading, please wait" 
		src="http://www.codeproject.com/ajax-loader.gif" />');
        }
        
        jQuery.ajax({
         type:"POST",
         url:"Portlet/Content/<%= portlet_ID %>/" + page +"/<%= portletName %>", 
         success: function(result) {
                      if(result.isOk == false)
                      {
                          $("#<%= portletContent %>").html(result.message);
                          $("#<%= "Header" + portletName %>").html("");
                      }    
                      else
                      {
                          $("#<%= portletContent %>").html(result);
                          $("#<%= "Header" + portletName %>").html
				("<%= ViewData["Title"] %>");
                          $(function() {
                            $("button, input:button, a", ".demo").button();
                            });
                      }   
                  },
         async:   true
        }); 
        }
    </script> 

    <%-- portlets/webpart generation   --%>
    

<div class="portlet ui-state-default" id="<%= portletName %>" style="HEIGHT: 2%">       

<div class="portlet-header">                

<div id="<%= "Header" + portletName %>" style="COLOR: white">Loading..... </div>

            </div>
 
            <%-- portlets/webpart content holder--%>                   

<table width="100%">
<tbody>
<tr>
<td>
<div class="portlet-content" id="<%= portletContent %>">
<img alt="Loading, please wait" src=http://www.codeproject.com/ajax-loader.gif 
önload="<%=" />() /> </div>
</td>
</tr>
</tbody>
</table>


    </div>
Content Controller Method

It's Portlet controller's controller method, it accepts portlet_ID, page_No and portletName. Portlet control invokes it using AJAX call. portlet_ID parameter is used to specify content source and page_No to slash down content list view accordance with provided parameters.

public ActionResult Content(int? portlet_ID, int page, string portletName)
        {
            // invalid portlet id
            if( portlet_ID == null )
                return View("ErrorPortalItem");

            #region declaration
            XmlNodeList objNL;
            StringBuilder str = new StringBuilder();
            // portlet page size 
            int pageSize = Convert.ToInt32
	   (System.Configuration.ConfigurationManager.AppSettings
		["PageSize"].ToString());
            string title = "";
            string ItemLink = "";
            string ItemTitle = "";
            int total_Items = 0;
            int last_Item_No = 0;
            #endregion
         
            #region loading RSS feed
            string link = ((WebApplication.Models.ds) 
		this.HttpContext.Application["data"]).Portlet.FindByPortlet_ID
		( Convert.ToInt32( portlet_ID ) ).Link;
            XmlDocument objDoc = new XmlDocument();
            

            try
            {
                objDoc.Load(link);
            }
            catch
            {
                // invalid portlet id
                return View("ErrorPortalItem");
            }
            #endregion

             #region parsing RSS parent node
            objNL = objDoc.SelectNodes("rss/channel");
            if (null != objNL)
            {
                // get title for portlet
                title = objNL[0].ChildNodes[0].InnerText;
            }
            #endregion

            #region parsing items in RSS feed
            if (null != objDoc)
            {
                objNL = objDoc.SelectNodes("rss/channel/item");
                if (null != objNL)
                {
                    int counter = 1;
                    string description = "";
                    total_Items = objNL.Count;

                    foreach (XmlNode XNode in objNL)
                    {
                        if (counter >= ((page * pageSize) - pageSize) && 
					counter <= (page * pageSize))
                        {
                            str.Append("<li>");
                            ItemTitle = "";
                            description = "";
                            foreach (XmlNode XNodeNested in XNode.ChildNodes)
                            {
                                switch (XNodeNested.Name)
                                {
                                    case "description":
                                        description = XNodeNested.InnerText;
                                        break;
                                    case "title":
                                        ItemTitle = XNodeNested.InnerText;
                                        break;
                                    case "link":
                                        ItemLink = XNodeNested.InnerText;
                                        break;
                                }
                            }
                            
                            str.Append("</a></li><a>");
                            last_Item_No = counter;
                        }
                        counter++;
                    }
                }
            }
            #endregion         

            #region setting view naviation variables
            double temp = total_Items / pageSize;
            int possible_Pages = Convert.ToInt32(Math.Ceiling(temp));

            ViewData["Next_Page"] = page + 1;
            ViewData["Previous_Page"] = page - 1;

            if ( ( page + 1 ) > possible_Pages)
                ViewData["Is_Next_Page_Possible"] = false; 
            else
                ViewData["Is_Next_Page_Possible"] = true;

            if ( ( page  ) == 1)
                ViewData["Is_Previous_Page_Possible"] = false;
            else
                ViewData["Is_Previous_Page_Possible"] = true;
            #endregion

            #region setting views content variables
            ViewData["content"] = str.ToString();
            ViewData["title"] = title;
            ViewData["portletName"] = portletName;
            #endregion
            return View();
}

Detail View

When content list item's description is outsized it constraint size or it contain html document, then it need to be display in Dialog. Detail button is provided to view detail which would invoke JavaScript OpenDialog function.

<% 
        string funcItem = "func" + ViewData["portletName"].ToString();
        string previous_Function = funcItem + 
		"(" + ViewData["Previous_Page"].ToString() + ")";
        string next_Function = funcItem + "(" + ViewData["Next_Page"].ToString() + ")"; 
%>


<table width="100%">
<tbody>
<tr>
<td><%= ViewData["Header"].ToString() %> <%-- RSS feed content holder --%> 
<%= ViewData["content"].ToString()%> </td>
</tr>

<tr>
<td><%-- content navigation--%> <%-- 
<div class="demo">--%> <%-- 
<p id="<%= "PortletContentLoading" + ViewData["item"].ToString() %>">
<img style="width:640px; height:480px"  alt="Loading, please wait" 
src="http://www.codeproject.com/ajax-loader.gif" /> --%> 
<% if (Convert.ToBoolean(ViewData["Is_Previous_Page_Possible"])) {%> 
<input style="padding: 0em;" class="demo ui-button ui-widget ui-state-default 
ui-corner-all" 
value=" < " önclick="<%=" previous_function="" %="" type="button"> /> 
<%}%> <% if (Convert.ToBoolean(ViewData["Is_Next_Page_Possible"])) {%> 
<input style="padding: 0em;" class="demo ui-button ui-widget ui-state-default 
ui-corner-all" value=" > 
" önclick="<%=" next_function="" %="" type="button"> /> <%}%> <%-- </p>
</div>
--%>  </td>
</tr>
</tbody>
</table>      

On calling the method get AJAX request is generated to Portlet controller's GetItemDetail controller method. It consumes portlet_ID and item_No to get specific portlet's specific item's description. Method will return required description of an Item to be displayed in dialog.

 
       public ActionResult GetItemDetail(int? portlet_ID, int? item_No)
        {
            // invalid portlet id
            if (portlet_ID == null || item_No == null)
                return View("ErrorPortalItem");
           
            #region declaration
            XmlNodeList objNL;
            StringBuilder str = new StringBuilder();
            
            // portlet page size 
            int pageSize = Convert.ToInt32
		(System.Configuration.ConfigurationManager.AppSettings
			["PageSize"].ToString());

            string title = "";
            string imagePath = "";
            string ItemName = "Item" + portlet_ID.ToString();
            string ItemLink = "";
            string ItemTitle = "";
            #endregion

            #region loading RSS path
            string link = ((WebApplication.Models.ds)
		this.HttpContext.Application["data"]).Portlet.FindByPortlet_ID
		(Convert.ToInt32(portlet_ID)).Link;
            XmlDocument objDoc = new XmlDocument();
          
            try
            {
                objDoc.Load(link);
            }
            catch
            {
                // invalid portlet id
                return View("ErrorPortalItem");
            }
            #endregion
           
            #region parsing RSS header for title
            objNL = objDoc.SelectNodes("rss/channel");
            if (null != objNL)
            {
                // get title for portlet
                title = objNL[0].ChildNodes[0].InnerText;
            }
            #endregion

            #region get image path for portlet from RSS feed
            objNL = objDoc.SelectNodes("rss/channel/image");
            if (null != objNL)
            {
                objNL = objDoc.SelectNodes("rss/channel/image/url");
                if (objNL.Count != 0)
                    imagePath = objNL[0].InnerText;
                else
                    imagePath = "";
            }
            #endregion

            #region content to be generated from RSS feed
            int total_Items = 0;
            if (null != objDoc)
            {
                objNL = objDoc.SelectNodes("rss/channel/item");
                if (null != objNL)
                {
                    int counter = 1;
                    string description = "";

                    total_Items = objNL.Count;
                    foreach (XmlNode XNode in objNL)
                    {
                        if (counter == item_No)
                        {
                            ItemTitle = "";
                            description = "";
                            foreach (XmlNode XNodeNested in XNode.ChildNodes)
                            {
                                switch (XNodeNested.Name)
                                {
                                    case "description":
                                        description = XNodeNested.InnerText;
                                        break;
                                    case "title":
                                        ItemTitle = XNodeNested.InnerText;
                                        break;
                                    case "link":
                                        ItemLink = XNodeNested.InnerText;
                                        break;
                                }
                            }
                            break;
                        }
                        counter++;
                    }
                    str.Append(description);
                }
            }
            #endregion

            #region setting view content variables
            ViewData["detail"] = str.ToString();
            ViewData["imagePath"] = imagePath;
            ViewData["title"] = title;
            #endregion

            return View("ItemDetail");
        }

Customization through Drag and Drop

Drag and drop personalization is accomplished through JQuery Library, which provides portlet placement and category change feature.

webpartsMVC/Drag_With_In_Tab.jpg

webpartsMVC/TabDrop.jpg

Droppable functionality

When user wants to change Portlet/Webpart category, he needs to drag and drop particular Portlet/Webpart to that specific category tab. To implement this functionality, jquery.ui.draggable.js is inducted in the solution. When Portlet/Webpart is dragged and dropped onto tab associated droppable method is called, during that mean time PortletsPlacementManager method is called which performs placement settlement in repository.

 var current_Column_ID = "";
        var portlet_Header_Icon;
        var portlet_Item_Name = "";
        $(function() {
		    var $tabs = $("#tabs").tabs();
		    var $tab_items = $("ul:first li",$tabs).droppable({
			    accept: '.column div' ,
			    tolerance: 'pointer',
			    opacity: .50,
                containment: '.container',
                cursor: 'move',
                cursorAt: { cursor: 'move', top: -155, left: -55, bottom: 0 }, 
    			
			    drop: function(ev, ui) { 
    			    
			        var $item = $(this);
				    var $list = $($item.find('a').attr
					('href')).find('.column')[0];
                    
                    PortletsPlacementManager($($item.find('a').attr('href')).find
		   ('.column').attr("id"),current_Column_ID,portlet_Item_Name,0,1);
                    
				    ui.draggable.hide('slow', function() {
					    $tabs.tabs('select', $tab_items.index
								($item));
					    $(this).appendTo($list).show('slow');
				    });
    				
				    $(this).find(".portlet-content").toggle(true);
    			    
			    }
		    });
	    });
Placement Management

Whenever Portlet/Webpart customization took place, PortletsPlacementManager JavaScript method would be called to synchronize portlet's placement adjustment with repository.

 
       function PortletsPlacementManager(column_ID,sender_Column_ID,
			portlet_ID,row_No,is_Drop) {
         jQuery.ajax({
         type:"POST",
         url:"Portlet/PortletsPlacementManager/" + column_ID + "/" + 
			portlet_ID +"/" + row_No + "/" + is_Drop  , 
         success: function(result) {
                       
                      if(result.isOk != false)
                      {
                        if( is_Drop = 1 )
                        {
                          TotalCatetogoryPortlets(column_ID);
                          TotalCatetogoryPortlets(sender_Column_ID);
                        }
                      }   
                  },
         async: true
        }); 
        }
Calculate Current Category Portlet

Whenever portlet/Webpart category changes, portlet in specific category changes as well, to have synchronize view with repository, category from where portlet is transferred and where its transfer required reevaluation it's portlets count, for that purpose TotalCatetogoryPortlets method is called, it take column id (category id is resided within it) and returns current total number of portlets assigned to that category.

  function TotalCatetogoryPortlets(column_ID) {
        
         jQuery.ajax({
         type:"POST",
         url:"Portlet/TotalCatetogoryPortlets/" + column_ID, 
         success: function(result) {
                      if(result.isOk != false)
                      {
                          var name = "#tab" + column_ID.substring(4);
                          $(name).html( result );
                      }   
                  },
         async:   true
        }); 
        }

Managing Portlets Status

When uses want to remove or disable Portlet/Webpart from his view, he just needs to cancel that particular Portlet/Webpart. By canceling it, that Portlet/Webpart shall have disabled status. To reactivate it, user needs to go to Disabled Portlet list and just click restore button at top of header.

webpartsMVC/Disabled_Portlets.jpg

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Hasan Hyder
Software Developer
Pakistan Pakistan
Member
Organisation
21 members

No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionWay better than jdash .net - they copied your thoughts and technologymemberlongnights2 May '13 - 17:35 
Jdash . net is trying to do something like this, but they embed charts, Poke tongue | ;-P
 
1) can you show how to embed other controls inside the portlets, iframes or google maps?
2) how to add and/remove widgets dynamically like dynamic dashboards .net
3) simplemembership would be nice too
AnswerRe: Way better than jdash .net - they copied your thoughts and technologygroupHasan Hyder4 May '13 - 1:51 
you can add diffrent portlet just directing the portlet to controller that provides your desire view in this case ( feed, MSChart or google map ) its not much the work ( if you have a problem please let me know ). If you follow this article video there you will find dynamic add/remove feature.
QuestionMembership / Loginmemberlongnights29 Nov '12 - 18:08 
Hi, how can we add new asp simple membership /login to this. Big Grin | :-D
 
Thanks for the post.
AnswerRe: Membership / LogingroupHasan Hyder30 Nov '12 - 18:36 
This link can help you out.
Thanks,
GeneralRe: Membership / Loginmemberlongnights4 Dec '12 - 11:05 
Thanks, but I was asking about the new simpleMembership, so it works with oAuth etc
QuestionBigger panelsmemberMember 144108916 Oct '12 - 13:04 
Hi, great article. Could it be extended to allow for portlets that take up two column widths?
AnswerRe: Bigger panelsgroupHasan Hyder16 Oct '12 - 19:10 
Hi,
 
Thanks for your appreciation, now to your question, yes you can change column width, for that you need to do some changes in TabPage.aspx file, you need to change the width of the div
<div id='<%= "portletColumn3" + catRow["Category_ID"].ToString() %>'   class="column" style="margin: 0 0px 0px 0px; padding: 5px; font-size: 1.2em; width: 285px;">
 
 
with name portletColumn1, portletColumn2 and portletColumn3 change width width: 285px to the your desired width.
 
for example
 
<div id='<%= "portletColumn3" + catRow["Category_ID"].ToString() %>'   class="column" style="margin: 0 0px 0px 0px; padding: 5px; font-size: 1.2em; width: 570px;">

GeneralRe: Bigger panelsmemberMember 144108916 Oct '12 - 19:31 
Thanks very much for your quick reply.
 
I was actually thinking about having different sized panels (i.e. a mixture) whereby some panels take up one column and some take up two.
 
I am designing a portal site at the moment and some of the functionality that I want in a portlet would need a wider space (say 500px) and some could fit in the current 285px.
 
I am not sure that this possible in the current framework?
GeneralMy vote of 5membermanoj kumar choubey31 Aug '12 - 4:49 
Nice ..... Smile | :)
GeneralRe: My vote of 5groupHasan Hyder19 Sep '12 - 1:40 
Thanks, Smile | :)
GeneralMy vote of 5membersupriya chaladi16 Aug '12 - 23:51 
excellent
GeneralRe: My vote of 5groupHasan Hyder19 Sep '12 - 1:40 
Thanks, Smile | :)
QuestionHosting the project under IIS does't work [modified]memberprateek.gupta19839 Apr '12 - 0:00 
I tried running this application using file system, which seems to be running fine.But as soon as I host this aplication under IIS and tried to explore the site,I am getting script error "Microsoft JScript runtime error: '$' is undefined". I am getting this error in Portal.aspx ($(function() { .... line 10).
I have hosted this application under IIS 7.5(Framework used:2.0)
 

Thanks,
Prateek

modified 9 Apr '12 - 6:08.

AnswerRe: Hosting the project under IIS does't workgroupHasan Hyder15 Apr '12 - 19:48 
Open web.config file on project's root directory, goto <appsetting> element; in its hierarchy you will find <add> element with key GSite set it value to the name of your virtual directory upon which you hosted this application e.g http://localhost/Portlet then value will be "Portlet/" or just "Portlet" i don't remember it exactly.
<add key="GSite" value="Portlet/"/>
 
I am planning host this application live, it will be better for you to understand its features. Hope it would work, and sorry for late reply.
 
Regards,
QuestionVS2010 [modified]memberLesF18 Mar '12 - 11:22 
I know we hate revisiting code we left behind so long ago, but is there any chance of getting this imported to VS2010 and maybe the latest ASP.Net/MVC, or is it outdated for these versions?
 
(or at least add version numbers to the prerequisites list)
 
Thanx

modified 18 Mar '12 - 17:37.

AnswerRe: VS2010groupHasan Hyder19 Mar '12 - 16:59 
In VS2010 conversion wizard can help you through, while in VS2008, VS2008 SP1 is mandatory, you couldn't have MVC 2 build without it.
QuestionScreenshots are not goodmemberNandaKumer4 Dec '11 - 14:49 
Good article except the images
AnswerRe: Screenshots are not goodgroupHasan Hyder5 Dec '11 - 19:55 
yep, Big Grin | :-D
GeneralMy vote of 5memberUday P.Singh4 Dec '11 - 7:18 
Great explanation very helpful Smile | :)
GeneralRe: My vote of 5groupHasan Hyder5 Dec '11 - 19:47 
Thanks, Smile | :)
BugDoes not build in ASP.net 4.0 - helpmemberMember 81923965 Oct '11 - 17:00 
Server Error in '/' Application.
Configuration Error
Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.
 
Parser Error Message: Could not load file or assembly 'System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.
 
Source Error:
 
Line 25:     <compilation debug="true" targetFramework="4.0">
Line 26:       <assemblies>
Line 27:         <add assembly="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
Line 28:         <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
Line 29:         <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
 

Source File: H:\_my_Code\MVC_Application_portal\MVC_Application\WebApplication\web.config    Line: 27
 
Assembly Load Trace: The following information can be helpful to determine why the assembly 'System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' could not be loaded.
 
=== Pre-bind state information ===
LOG: User = t
LOG: DisplayName = System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
 (Fully-specified)
LOG: Appbase = file:///H:/_my_Code/MVC_Application_portal/MVC_Application/WebApplication/
LOG: Initial PrivatePath = H:\_my_Code\MVC_Application_portal\MVC_Application\WebApplication\bin
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: H:\_my_Code\MVC_Application_portal\MVC_Application\WebApplication\web.config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
LOG: Attempting download of new URL file:///C:/Users/Tester/AppData/Local/Temp/Temporary ASP.NET Files/root/889dc2c2/fe9ad172/System.Web.Mvc.DLL.
LOG: Attempting download of new URL file:///C:/Users/Tester/AppData/Local/Temp/Temporary ASP.NET Files/root/889dc2c2/fe9ad172/System.Web.Mvc/System.Web.Mvc.DLL.
LOG: Attempting download of new URL file:///H:/_my_Code/MVC_Application_portal/MVC_Application/WebApplication/bin/System.Web.Mvc.DLL.
LOG: Attempting download of new URL file:///H:/_my_Code/MVC_Application_portal/MVC_Application/WebApplication/bin/System.Web.Mvc/System.Web.Mvc.DLL.
LOG: Attempting download of new URL file:///C:/Users/Tester/AppData/Local/Temp/Temporary ASP.NET Files/root/889dc2c2/fe9ad172/System.Web.Mvc.EXE.
LOG: Attempting download of new URL file:///C:/Users/Tester/AppData/Local/Temp/Temporary ASP.NET Files/root/889dc2c2/fe9ad172/System.Web.Mvc/System.Web.Mvc.EXE.
LOG: Attempting download of new URL file:///H:/_my_Code/MVC_Application_portal/MVC_Application/WebApplication/bin/System.Web.Mvc.EXE.
LOG: Attempting download of new URL file:///H:/_my_Code/MVC_Application_portal/MVC_Application/WebApplication/bin/System.Web.Mvc/System.Web.Mvc.EXE.
 

Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.237

AnswerRe: Does not build in ASP.net 4.0 - helpgroupHasan Hyder6 Oct '11 - 4:52 
You need to install ASP.NET MVC 1.0 to have a run.
QuestionGoodmemberVenumunna19 Sep '11 - 16:32 
Good way of developing portal by MVC. I think the challenging part will be maintaining the position of the portlets/webparts. Do you have any ideas how to maintain the positions of portlets/webparts?
AnswerRe: GoodgroupHasan Hyder20 Sep '11 - 2:48 
If you just glance over at Data Model you shall observe "column_No" and "Row_Sequence" properties in "Portlet" Entity, it helps to manage portlet/Webpart relative positions. Hope; i respond it well.
 
Thanks,
Wink | ;)
Questiongood articlememberMember 439094622 Aug '11 - 4:13 
Smile | :)
AnswerRe: good articlegroupHasan Hyder31 Aug '11 - 18:26 
Thanks Wink | ;)
GeneralMy vote of 5memberMonjurul Habib5 Jun '11 - 8:23 
nice one.
GeneralRe: My vote of 5groupHasan Hyder5 Jun '11 - 21:40 
Thanks Big Grin | :-D
GeneralMy vote of 5memberkumarvinit863 Jun '11 - 22:22 
this is a good example for freshers
GeneralRe: My vote of 5groupHasan Hyder4 Jun '11 - 5:19 
Thanks Smile | :)
GeneralRe: My vote of 5memberMember 439094622 Aug '11 - 4:11 
Smile | :)
GeneralMy vote of 5memberIFFI1 Jun '11 - 3:26 
Nice work Hasan.
 
Keep it up.
GeneralRe: My vote of 5groupHasan Hyder3 Jun '11 - 18:30 
Thanks Smile | :)
GeneralDynamic user controlsmemberNeetflash31 May '11 - 23:38 
Could your solution in MVC allow for dynamic loading of user controls compiled into a separate DLL like is normal with webforms?
GeneralRe: Dynamic user controlsgroupHasan Hyder3 Jun '11 - 18:49 
In MVC Framework controller and Model are compile into DLL, and view ( .aspx, .ascx ) doesn't. but you can dynamically decide the view from controller.
GeneralRe: Dynamic user controlsmemberRajesh Pillai6 Dec '11 - 7:42 
Just a note... In case you are using MVC Razor view engine, then it can be compiled into its own separate assembly..
Enjoy Life,
Rajesh Pillai
http://geekswithblogs.net/rajeshpillai
 


 

GeneralMy vote of 2mvpOmar Al Zabir31 May '11 - 0:16 
Good article, but not a good use of ASP.NET MVC.
GeneralRe: My vote of 2groupHasan Hyder31 May '11 - 9:01 
That was very harsh, Frown | :( you said good and you gave 2. Please reconsider and re-vote.
modified on Wednesday, June 1, 2011 12:16 AM

GeneralMy vote of 5membersaxenaabhi622 May '11 - 20:30 
Great work...
GeneralRe: My vote of 5groupHasan Hyder25 May '11 - 23:23 
Thanks Smile | :)
GeneralMy vote of 5memberantrim7 Mar '11 - 7:31 
Better implementation than asp.net web part framework.
GeneralRe: My vote of 5groupHasan Hyder9 Mar '11 - 7:56 
That was something, thanks Big Grin | :-D
GeneralGreat Articlemembermicrovox2 Mar '11 - 4:33 
Hasan,
 
Thanks for posting this. Great article.
 
Mike
GeneralRe: Great ArticlegroupHasan Hyder4 Mar '11 - 4:03 
Thanks Wink | ;)
GeneralMy vote of 5memberjim lahey3 Feb '11 - 1:21 
very nice
GeneralRe: My vote of 5groupHasan Hyder5 Feb '11 - 2:10 
Thank You! Smile | :)
GeneralGood!!!membershakil030400331 Jan '11 - 21:59 
Good one!!!
Md. Shakil Ahmed.

GeneralRe: Good!!!groupHasan Hyder31 Jan '11 - 22:27 
Thank You! Smile | :)
GeneralMy vote of 5memberSunasara Imdadhusen30 Jan '11 - 22:49 
Good one!
GeneralRe: My vote of 5groupHasan Hyder31 Jan '11 - 22:15 
Thank You! Big Grin | :-D

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 31 Aug 2012
Article Copyright 2011 by Hasan Hyder
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid