Managing Users and Roles

by Vishwa 5. January 2007 07:10

The following example will demonstrate as how to manage registered users, activate or deactivate them assign or remove role(s) in ASP.Net. My assumption is, you already have a page which allows users to register and now you would like to activate the user and assign a role so that they can login to your web site. I have created two page, which resides in Admin area of web site. You will be required to make some changes such as Master Page File, Namespace, Base Page and Content Place Holder ID etc. in order to properly compile and work with you project. The first page will allow you to search and find one or more registered users and second page will allow you to activate and assign a role.
 

Note: My User Profile contains additional fields such as First Name, Last Name, Address and Phone Number, if you are not using in your profile, you can remove it or change it as per your user profile.

 

Users.Aspx

 

Code Snippet
  1. <%@ Page Language="VB" MasterPageFile="~/WebSite.master"
  2. AutoEventWireup="false" CodeFile="Users.aspx.vb" Inherits="Admin_Users"
  3. title="VishwaMohan.Com | Admin | Manage Users" %>
  4. <asp:Content ID="conContentManage" ContentPlaceHolderID="cphMainContent" Runat="Server">
  5. <div style="text-align:center">
  6. <table cellpadding="2" cellspacing="0" border="0" width="100%" style="text-align:center">
  7. <tr>
  8. <td id="content" width="100%" valign="top" height="100%" class="darkgray_row" style="text-align:center">
  9. <table cellpadding="0" cellspacing="0" border="0" width="100%" style="text-align:center" >
  10. <tr>
  11. <td valign="top" style="text-align:center"><h3 class="lighgray_row" style="text-align:center">Account Management</h3>
  12. <br />
  13. <b>- Total registered users: <asp:Literal runat="server" ID="lblTotUsers" /><br />
  14. - Users online now: <asp:Literal runat="server" ID="lblOnlineUsers" /></b>
  15. <p>
  16. Click one of the following link to display all users whose name begins with that letter:
  17. </p>
  18. </td>
  19. </tr>
  20. <tr>
  21. <td style="text-align:center">
  22. <asp:Repeater runat="server" ID="rptAlphabet" OnItemCommand="rptAlphabet_ItemCommand">
  23. <ItemTemplate><asp:LinkButton ID="lnbLinkButton" runat="server" Text='<%# Container.DataItem %>'
  24. CommandArgument='<%# Container.DataItem %>' />&nbsp;&nbsp;
  25. </ItemTemplate>
  26. </asp:Repeater>
  27. </td>
  28. </tr>
  29. <tr>
  30. <td style="text-align:center">
  31. <br />
  32. Otherwise use the controls below to search users by partial username or e-mail:
  33. <br />
  34. </td>
  35. </tr>
  36. <tr>
  37. <td height="50px;" style="text-align:center">
  38. <asp:DropDownList runat="server" ID="ddlSearchTypes">
  39. <asp:ListItem Text="UserName" Selected="true" />
  40. <asp:ListItem Text="E-mail" />
  41. </asp:DropDownList>
  42. Contains
  43. <asp:TextBox runat="server" ID="txtSearchText" />
  44. <asp:Button runat="server" ID="btnSearch" Text="Search" CssClass="button" OnClick="btnSearch_Click" />
  45. <br />
  46. </td>
  47. </tr>
  48. <tr>
  49. <td style="text-align:center">
  50. <asp:GridView ID="gvwUsers" runat="server" AutoGenerateColumns="false" DataKeyNames="UserName"
  51. OnRowCreated="gvwUsers_RowCreated" Width="100%" PagerSettings-Mode="NumericFirstLast"
  52. PageSize="10" >
  53. <Columns>
  54. <asp:BoundField HeaderText="UserName" DataField="UserName" />
  55. <asp:HyperLinkField HeaderText="E-mail" DataTextField="Email" DataNavigateUrlFormatString="mailto:{0}" DataNavigateUrlFields="Email" />
  56. <asp:BoundField HeaderText="Created" DataField="CreationDate" DataFormatString="{0:MM/dd/yy h:mm tt}" />
  57. <asp:BoundField HeaderText="Last activity" DataField="LastActivityDate" DataFormatString="{0:MM/dd/yy h:mm tt}" />
  58. <asp:CheckBoxField HeaderText="Appr." DataField="IsApproved" HeaderStyle-HorizontalAlign="Center" ItemStyle-HorizontalAlign="Center" />
  59. <asp:HyperLinkField Text="<img src='../images/edit.gif' border='0' />" DataNavigateUrlFormatString="EditUser.aspx?UserName={0}" DataNavigateUrlFields="UserName" />
  60. <asp:ButtonField CommandName="Delete" ButtonType="Image" ImageUrl="~/images/delete.gif" />
  61. </Columns>
  62. <EmptyDataTemplate><b>No users found for the specified criteria</b></EmptyDataTemplate>
  63. </asp:GridView>
  64. </td>
  65. </tr>
  66. </table>
  67. </td>
  68. </tr>
  69. </table>
  70. </div>
  71. </asp:Content>

Users.Aspx.vb

Option Explicit On
 
Option Strict On
 
Partial Class Admin_Users
 
    Inherits BasePage
 
    Private allUsers As MembershipUserCollection = Membership.GetAllUsers
 
 
 
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
 
        If Not Me.IsPostBack Then
 
            lblTotUsers.Text = allUsers.Count.ToString
 
            lblOnlineUsers.Text = Membership.GetNumberOfUsersOnline.ToString
 
            Dim alphabet As String() = _
 
                "A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;W;X;Y;Z;All".Split(CChar(";"))
 
            rptAlphabet.DataSource = alphabet
 
            rptAlphabet.DataBind()
 
        End If
 
    End Sub
 
 
 
    Private Sub BindUsers(ByVal reloadAllUsers As Boolean)
 
        If reloadAllUsers Then
 
            allUsers = Membership.GetAllUsers
 
        End If
 
 
 
        Dim users As MembershipUserCollection = Nothing
 
 
 
        Dim searchText As String = ""
 
        If Not String.IsNullOrEmpty(gvwUsers.Attributes("SearchText")) Then
 
            searchText = gvwUsers.Attributes("SearchText")
 
        End If
 
 
 
        Dim searchByEmail As Boolean = False
 
        If Not String.IsNullOrEmpty(gvwUsers.Attributes("SearchByEmail")) Then
 
            searchByEmail = Boolean.Parse(gvwUsers.Attributes("SearchByEmail"))
 
        End If
 
 
 
        If searchText.Length > 0 Then
 
            If searchByEmail Then
 
                users = Membership.FindUsersByEmail(searchText)
 
            Else
 
                users = Membership.FindUsersByName(searchText)
 
            End If
 
        Else
 
            users = allUsers
 
        End If
 
 
 
        gvwUsers.DataSource = users
 
        gvwUsers.DataBind()
 
    End Sub
 
 
 
    Protected Sub rptAlphabet_ItemCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.RepeaterCommandEventArgs) Handles rptAlphabet.ItemCommand
 
        gvwUsers.Attributes.Add("SearchByEmail", Boolean.FalseString)
 
 
 
        If e.CommandArgument.ToString.Length = 1 Then
 
            gvwUsers.Attributes.Add("SearchText", e.CommandArgument.ToString + "%")
 
            BindUsers(False)
 
        Else
 
            gvwUsers.Attributes.Add("SearchText", "")
 
            BindUsers(False)
 
        End If
 
    End Sub
 
 
 
    Protected Sub btnSearch_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSearch.Click
 
        Dim searchByEmail As Boolean = (ddlSearchTypes.SelectedValue = "E-mail")
 
        gvwUsers.Attributes.Add("SearchText", "%" + txtSearchText.Text + "%")
 
        gvwUsers.Attributes.Add("SearchByEmail", searchByEmail.ToString)
 
        BindUsers(False)
 
    End Sub
 
 
 
    Protected Sub gvwUsers_RowCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvwUsers.RowCreated
 
        If e.Row.RowType = DataControlRowType.DataRow Then
 
            Dim btn As ImageButton = CType(e.Row.Cells(6).Controls(0), ImageButton)
 
            btn.OnClientClick = "if (confirm('Are you sure you want to delete this user account?') == false) return false;"
 
        End If
 
    End Sub
 
    Protected Sub gvwUsers_RowDeleting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeleteEventArgs) Handles gvwUsers.RowDeleting
 
        Try
 
            Dim userName As String = gvwUsers.DataKeys(e.RowIndex).Value.ToString
 
            ProfileManager.DeleteProfile(userName)
 
            Membership.DeleteUser(userName)
 
            BindUsers(True)
 
            lblTotUsers.Text = allUsers.Count.ToString
 
        Catch exc As Exception
 
            lblOnlineUsers.Text = exc.Message
 
        End Try
 
    End Sub
 
End Class
 

EditUser.Aspx

Code Snippet
  1. <%@ Page Language="VB" MasterPageFile="~/WebSite.master"
  2. AutoEventWireup="false" CodeFile="EditUser.aspx.vb" Inherits="Admin_EditUser"
  3. title="VishwaMohan.Com | Admin | Edit Users" %>
  4. <asp:Content ID="conContentEditUser" ContentPlaceHolderID="cphMainContent" Runat="Server">
  5. <div style="text-align:center">
  6. <table cellpadding="2" cellspacing="0" border="0" width="100%" style="text-align:center">
  7. <tr>
  8. <td id="content" width="100%" valign="top" height="100%" class="darkgray_row" align="left">
  9. <table cellpadding="0" cellspacing="0" border="0" width="100%" style="text-align:center" >
  10. <tr>
  11. <td valign="top" colspan="2" style="text-align:center">
  12. <h3 class="lighgray_row" style="text-align:center">Edit User Account</h3>
  13. </td>
  14. </tr>
  15. <tr>
  16. <td width="200px" nowrap></td>
  17. <td>
  18. <table cellpadding="2" border="0" width="100%" visible=false>
  19. <tr>
  20. <td >User Name:</td>
  21. <td >
  22. <asp:Literal ID="lblUserName" runat="server"></asp:Literal></td>
  23. </tr>
  24. <tr>
  25. <td >
  26. First Name:</td>
  27. <td>
  28. <asp:Label ID="lblFirstName" runat="server"/></td>
  29. </tr>
  30. <tr>
  31. <td >
  32. Last Name:</td>
  33. <td>
  34. <asp:Label ID="lblLastName" runat="server"/></td>
  35. </tr>
  36. <tr>
  37. <td colspan="2"><hr /></td>
  38. </tr>
  39. <tr>
  40. <td >
  41. E-Mail:</td>
  42. <td>
  43. <asp:HyperLink ID="lnkEmail" runat="server">[lnkEmail]</asp:HyperLink></td>
  44. </tr>
  45. <tr>
  46. <td >
  47. Address:</td>
  48. <td>
  49. <asp:Label ID="lblAddress" runat="server"/></td>
  50. </tr>
  51. <tr>
  52. <td >
  53. Phone:</td>
  54. <td>
  55. <asp:Label ID="lblPhone" runat="server"/></td>
  56. </tr>
  57. <tr>
  58. <td colspan="2"><hr /></td>
  59. </tr>
  60. <tr>
  61. <td >
  62. Registered:</td>
  63. <td>
  64. <asp:Literal ID="lblRegistered" runat="server"></asp:Literal></td>
  65. </tr>
  66. <tr>
  67. <td >
  68. Last Login:</td>
  69. <td>
  70. <asp:Literal ID="lblLastLogin" runat="server"></asp:Literal></td>
  71. </tr>
  72. <tr>
  73. <td >
  74. Last Activity</td>
  75. <td>
  76. <asp:Literal ID="lblLastActivity" runat="server"></asp:Literal></td>
  77. </tr>
  78. <tr>
  79. <td colspan="2"><hr /></td>
  80. </tr>
  81. <tr>
  82. <td >
  83. Online Now:</td>
  84. <td>
  85. <asp:CheckBox ID="chkOnlineNow" runat="server" Enabled="False" /></td>
  86. </tr>
  87. <tr>
  88. <td >
  89. Approved:</td>
  90. <td>
  91. <asp:CheckBox ID="chkApproved" runat="server" AutoPostBack="True" />&nbsp;&nbsp; If approved, make sure a role is assigned.</td>
  92. </tr>
  93. <tr>
  94. <td >
  95. Locked Out:</td>
  96. <td>
  97. <asp:CheckBox ID="chkLockedOut" runat="server" AutoPostBack="True" /></td>
  98. </tr>
  99. </table>
  100. </td>
  101. </tr>
  102. <tr>
  103. <td colspan="2" style="text-align:center">
  104. <h4 class="lighgray_row" style="text-align:center">Edit user's roles</h4>
  105. <br />
  106. <asp:CheckBoxList ID="chklRoles" runat="server" CellSpacing="4" RepeatColumns="5"/>
  107. </td>
  108. <tr>
  109. <td class="sidebar"></td>
  110. <td>
  111. <table cellpadding="2" width="100%" border="0">
  112. <tr>
  113. <td align="right">
  114. <asp:Label ID="lblRolesFeedback" runat="server" Text="Roles updated successfully"
  115. Visible="False"></asp:Label>&nbsp;&nbsp;&nbsp;&nbsp;
  116. <asp:Button ID="btnUpdateRoles" runat="server" Text="Update" CssClass="button"/></td>
  117. </tr>
  118. <tr>
  119. <td align="right">
  120. Create new role:&nbsp;<asp:TextBox ID="txtNewRole" runat="server"></asp:TextBox>
  121. <asp:RequiredFieldValidator ID="rfvRequireNewRole" runat="server" ControlToValidate="txtNewRole"
  122. ErrorMessage="Role name is required." SetFocusOnError="True" ValidationGroup="CreateRole"></asp:RequiredFieldValidator>
  123. <asp:Button ID="btnCreateRole" runat="server" Text="Create" ValidationGroup="CreateRole" CssClass="button" /></td>
  124. </tr>
  125. </table>
  126. </td>
  127. </tr>
  128. </table>
  129. </td>
  130. </tr>
  131. </table>
  132. </div>
  133. </asp:Content>

 

 

EditUser.Aspx.vb

Option Explicit On
 
Option Strict On
 
Imports System.Collections
 
Imports System.Collections.Generic
 
 
 
 
 
Partial Class Admin_EditUser
 
    Inherits BasePage
 
    Dim userName As String = ""
 
 
 
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
 
        Try
 
            userName = Me.Request.QueryString("UserName")
 
            lblRolesFeedback.Visible = False
 
 
 
            If Not Me.IsPostBack Then
 
                ' show the user's details
 
                If userName.Length > 0 Then
 
                    Dim user As MembershipUser = Membership.GetUser(userName)
 
                    Me.lblUserName.Text = user.UserName
 
                    Me.lnkEmail.Text = user.Email
 
                    Me.lnkEmail.NavigateUrl = "mailto:" & user.Email
 
                    Me.lblRegistered.Text = user.CreationDate.ToString("f")
 
                    Me.lblLastLogin.Text = user.LastLoginDate.ToString("f")
 
                    Me.lblLastActivity.Text = user.LastActivityDate.ToString("f")
 
                    Me.chkOnlineNow.Checked = user.IsOnline
 
                    Me.chkApproved.Checked = user.IsApproved
 
                    Me.chkLockedOut.Checked = user.IsLockedOut
 
                    Me.chkLockedOut.Enabled = user.IsLockedOut
 
 
 
                    Dim userProfile As ProfileCommon = Me.Profile
 
                    userProfile = Me.Profile.GetProfile(userName)
 
                    Me.lblFirstName.Text = userProfile.FirstName
 
                    Me.lblLastName.Text = userProfile.LastName
 
                    Me.lblAddress.Text = userProfile.Address
 
                    Me.lblPhone.Text = userProfile.Phone
 
 
 
                    BindRoles()
 
                End If
 
            End If
 
        Catch exc As Exception
 
            ' Do nothing
 
        Finally
 
        End Try
 
    End Sub
 
 
 
    Private Sub BindRoles()
 
        Me.chklRoles.DataSource = Roles.GetAllRoles
 
        Me.chklRoles.DataBind()
 
        For Each role As String In Roles.GetRolesForUser(userName)
 
            Me.chklRoles.Items.FindByText(role).Selected = True
 
        Next
 
    End Sub
 
    Protected Sub chkApproved_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles chkApproved.CheckedChanged
 
        Try
 
            
 
            Dim user As MembershipUser = Membership.GetUser(userName)
 
            Dim userEmail As String = user.Email.ToString()
 
            user.IsApproved = chkApproved.Checked
 
            Membership.UpdateUser(user)
 
            If chkApproved.Checked Then
 
                Dim emailMsg As New System.Net.Mail.MailMessage
 
                Dim smtpClient As New System.Net.Mail.SmtpClient()
 
 
 
                emailMsg.From = New System.Net.Mail.MailAddress(ConfigurationManager.AppSettings.Item("AdminUserEmail").ToString())
 
                emailMsg.Subject = "Your Account has been Approved."
 
                emailMsg.Body = "Hello " & userName & vbCrLf & Space(15) & "Your Account has been Approved." & vbCrLf & vbCrLf & "See you online!" & vbCrLf & "- Vishwa Mohan"
 
                emailMsg.To.Add(userEmail)
 
                smtpClient.Send(emailMsg)
 
 
 
            End If
 
            Me.lblRolesFeedback.Text = "Approval status updated successfully."
 
        Catch exc As Exception
 
            Me.lblRolesFeedback.Text = exc.Message
 
        Finally
 
            Me.lblRolesFeedback.Visible = True
 
        End Try
 
    End Sub
 
 
 
    Protected Sub chkLockedOut_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles chkLockedOut.CheckedChanged
 
        If Not chkLockedOut.Checked Then
 
            Dim user As MembershipUser = Membership.GetUser(userName)
 
            user.UnlockUser()
 
            Me.chkLockedOut.Enabled = False
 
        End If
 
    End Sub
 
 
 
    Protected Sub btnUpdateRoles_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnUpdateRoles.Click
 
        ' first remove the user from all roles...
 
        Dim currRoles() As String = Roles.GetRolesForUser(userName)
 
        If currRoles.Length > 0 Then
 
            Roles.RemoveUserFromRoles(userName, currRoles)
 
            Me.lblRolesFeedback.Text = "Role removed from the User."
 
        End If
 
 
 
        ' and then add the user to the selected roles
 
        Dim newRoles As New List(Of String)
 
        For Each item As ListItem In chklRoles.Items
 
            If item.Selected Then
 
                newRoles.Add(item.Text)
 
                Me.lblRolesFeedback.Text = "New Role Added to the User."
 
            End If
 
        Next
 
        Dim userNames() As String = {userName}
 
        Roles.AddUsersToRoles(userNames, newRoles.ToArray)
 
        Me.lblRolesFeedback.Visible = True
 
    End Sub
 
 
 
    Protected Sub btnCreateRole_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnCreateRole.Click
 
        If Not Roles.RoleExists(txtNewRole.Text.Trim) Then
 
            Roles.CreateRole(txtNewRole.Text.Trim)
 
            BindRoles()
 
        End If
 
    End Sub
 
End Class
 

Users.Aspx Page at Run Time

 

Tags:

.NET

Comments (10) -

Cricket91
Cricket91 United States
3/16/2007 8:25:00 PM #

Great Code!!

Had A Quick question I've been looking in the forums when I came across your tuturial and my question is this. How do you restrict albums by users and not roles?

Thanks

vishwa
vishwa United States
3/18/2007 5:23:54 PM #

I think you can do it two ways. One you can assign each album to a user for view or not to view or you can go up to photo level driven based on user. But either way it will put more work on you to assign each user either all album or photos you want to share with him or her. Another way could be, creating more groups and splitting your albums, and then you can assign one user to one or more role or group.

Osiris
Osiris United States
9/5/2007 2:58:08 AM #

First, I think that your program is great. For my purposes I had to make the slight changes shown below. The problem is that in an asp.net 2.0 environment this line "Roles.AddUsersToRoles(userNames, newRoles.ToArray)" produces this error "Unable to cast object of type 'System.Object[]' to type 'System.String[]'."

Please let me know the best fix. Thanks.

Protected Sub btnUpdateRoles_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnUpdateRoles.Click

        ' first remove the user from all roles...
        Dim currRoles() As String = Roles.GetRolesForUser(userName)

        If currRoles.Length > 0 Then
            Roles.RemoveUserFromRoles(userName, currRoles)
            Me.lblRolesFeedback.Text = "Role removed from the User."
        End If

        ' and then add the user to the selected roles
        Dim newRoles As New ArrayList

        For Each item As ListItem In chklRoles.Items
            If item.Selected Then
                newRoles.Add(item.Text)
                Me.lblRolesFeedback.Text = "New Role Added to the User."
            End If
        Next

        Dim userNames() As String = {userName}
        Roles.AddUsersToRoles(userNames, newRoles.ToArray)
        Me.lblRolesFeedback.Visible = True

    End Sub

Osiris
Osiris United States
9/5/2007 3:15:18 AM #

Ignore my post. The problem was that I had not added this to my web.config file. But while I have your attention, I used asp:createuserwizard to create users and I changed password settings in web.config under providers.
minRequiredNonalphanumericCharacters="0"
minRequiredPasswordLength="6"
These changes have had no effect. What am I doing wrong? Thanks again.

Osiris
Osiris United States
9/5/2007 3:29:12 AM #

Sorry again. By adding defaultProvider="ISKSqlMembershipProvider"  to the membership node in web.config everything worked.

farooq
farooq India
12/17/2007 4:11:38 AM #

Hi vishwa,
Above post is very good,
I ve bounded the following to repeater
Dim alphabet As String() = _

"A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;W;X;Y;Z;All".Split(CChar(";"))

and my reuirement is if records are not available with the particular alphabet how can I hide it ,do I need to do coding plz suggest me,

Thanks

johnjam
johnjam United Kingdom
10/8/2008 12:11:40 PM #

Hello Vishwa,
Many thanks for leaving the code on your site, it works very well indeed.  
I am still learning ASP.NET but loved the way you coded this and it integrated
very well with my existing application.
It may be wise to point out to novices developers such as myself the setting required
in the web.config as your Note was a bit vague about FirstName and LastName etc
perhaps you could verify these settings in web.config        

            
                
                
                
                
            

        

Another small note to make, what about Password resetting?.

Once again many thanks for the code
Kind regards
Johnjam

Ajay Pant
Ajay Pant India
4/7/2009 6:06:35 AM #

Hello Vishwa, Many thanks for leaving the code on your site, it works very well indeed. I am still learning ASP.NET but loved the way you coded this and it integrated very well with my existing application.

i got some error when i use the editusers.aspx.vb of yours coding "Managing Users and Roles."

the following syntax shows the error in "profile word" says 'Type Expected '
Dim userprofile As Profile = Me.Load
please give me the solution

Thanks

Cast Iron Hibachi
Cast Iron Hibachi United States
3/1/2010 11:04:42 PM #

Zahvaljujemo se vam za dobro delovno mesto najlep?a hvala

Oswaldo Porrini
Oswaldo Porrini United Kingdom
5/22/2010 3:52:50 PM #

Have you ever considered adding more videos to your blog posts to keep the readers more entertained? I mean I just read through the entire article of yours and it was quite good but since I'm more of a visual learner,I found that to be more helpful well let me know how it turns out! I love what you guys are always up too. Such clever work and reporting! Keep up the great works guys I've added you guys to my blogroll. This is a great article thanks for sharing this informative information.. I will visit your blog regularly for some latest post.

Comments are closed

About Me

Me Hello,my name is
Vishwa Mohan Kumar, PMP
MCP SOA Certified Architect
I am a Software Architect. This blog is result of my experiments.

Flickr Photos

Calendar

<<  February 2012  >>
MoTuWeThFrSaSu
303112345
6789101112
13141516171819
20212223242526
2728291234
567891011

View posts in large calendar

Archive

Recent Comments

Comment RSS

Live Traffic Feed