2
\$\begingroup\$

I have menu that contains links to sections of website:

Products | Orders | Users
__________________________
Add      | Add    | Add
Update   | Update | Update
Delete   | Delete | Delete

Depending on what role user is in, they can see limited number of options, e.g. "User" can only see:

Products | Orders 
__________________
Add      | Add    
         |        
         |        

All of them redirect to the same page, but with different parameters. RedirectType (Products, Orders, Users) and RedirectTypeState (Add, Update, Delete). I would like to remove ugly @if(...) statements from this code and make it neater:

<table class="menu-table" border="0" cellspacing="2" cellpadding="2">
    <tr>
        <td width="70"><a asp-page="/Index" class="buttonmenu">Main page</a></td>
        <td width="50"><a asp-page="/Auth/Login" class="buttonmenu">Log on</a></td>
        <td width="65"></td>
        <td width="60"></td>
        <td width="40"></td>
        <td width="50"></td>
        <td width="50"></td>
    </tr>
    <tr>
        <td colspan="6" align="right">
            <table border="0" cellspacing="0" cellpadding="0">
                <tr class="HeaderStaticLabel">
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                <tr class="HeaderStaticLabel">
                    <td>@if(CanSee("products", "add")){<label>Products</label>}</td>
                    <td>@if(CanSee("orders", "add")){<label>Orders</label>}</td>
                    <td>@if(CanSee("users", "add")){<label>Users</label>}</td>
                </tr>
                <tr class="menu-table-add">
                    <td>@if(CanSee("products", "add")){<a asp-page="/Find/Index" asp-route-type="@RedirectTypes.Products" asp-route-state="@RedirectTypeStates.Add" class="buttonmenu">Add</a>}</td><td></td>
                    <td>@if(CanSee("orders", "add")){<a asp-page="/Find/Index" asp-route-type="@RedirectTypes.Orders" asp-route-state="@RedirectTypeStates.Add" asp-route-isMessageInfo="true" class="buttonmenu">Add</a>}</td>
                    <td>@if(CanSee("users", "add")){<a asp-page="/Find/Index" asp-route-type="@RedirectTypes.Users" asp-route-state="@RedirectTypeStates.Add" asp-route-isMessageInfo="false" class="buttonmenu">Add</a>}</td>
                </tr>
                <tr class="menu-table-update">
                    <td>@if(CanSee("products", "update")){<a asp-page="/Find/Index" asp-route-type="@RedirectTypes.Products" asp-route-state="@RedirectTypeStates.Update" asp-route-isMessageInfo="true" class="buttonmenu">Update</a>}</td>
                    <td>@if(CanSee("orders", "update")){<a asp-page="/Find/Index" asp-route-type="@RedirectTypes.Orders" asp-route-state="@RedirectTypeStates.Update" asp-route-isMessageInfo="false" class="buttonmenu">Update</a>}</td>
                    <td>@if(CanSee("users", "update")){<a asp-page="/Find/Index" asp-route-type="@RedirectTypes.Users" asp-route-state="@RedirectTypeStates.Update" class="buttonmenu">Update</a>}</td>
                </tr>
                <tr class="menu-table-delete">
                    <td>@if(CanSee("products", "delete")){<a asp-page="/Find/Index" asp-route-type="@RedirectTypes.Products" asp-route-state="@RedirectTypeStates.Delete" class="buttonmenu">Delete</a>}</td>
                    <td>@if(CanSee("orders", "delete")){<a asp-page="/Find/Index" asp-route-type="@RedirectTypes.Orders" asp-route-state="@RedirectTypeStates.Delete" asp-route-isMessageInfo="true" class="buttonmenu">Delete</a>}</td>
                    <td>@if(CanSee("users", "delete")){<a asp-page="/Find/Index" asp-route-type="@RedirectTypes.Users" asp-route-state="@RedirectTypeStates.Delete" asp-route-isMessageInfo="false" class="buttonmenu">Delete</a>}</td>
                </tr>
            </table>
        </td>
    </tr>
</table>

@functions
{
    bool CanSee(string claimName, string claimValue) => User.Identity.IsAuthenticated && User.HasClaim(claimName, claimValue);
}

Some of them have additional route parameters, such as asp-route-isMessageInfo.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

The problem is that you're running against the limitations of Razor here. Ideally you'd have a function that loops though the various options -- add, update, delete -- and for each generates a relevant <tr> and its accompanying <td>s based on the claims User has the rights to.

I'm guessing that's possible in Razor, but I fear you'd end up with a significant amount of methods that all call each other -- e.g. a function to create a <tr> block that calls a function to create a <td> line, etc. -- which wouldn't exactly make things clearer.

Would it be possible for you to go full ASP.NET Core MVC? That way you can have such code in classes, have extension methods for User, etc. I did so in a recent project and it works like a charm, while still being easy to maintain.

\$\endgroup\$
1
  • \$\begingroup\$ I have to stick to Razor Pages. I was thinking about storing a dictionary with mapping of claim to url. Then I would have 3 list of AddUrls, UpdateUrls, DeleteUrls, and foreach on each of them to render <td>'s in html, but I'm afraid that it would actually decrease readibility. \$\endgroup\$
    – FCin
    Nov 21, 2018 at 9:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.