Skip to content
This repository was archived by the owner on Feb 23, 2021. It is now read-only.

Add Controller for multiple areas sample #262

Merged
merged 4 commits into from
Aug 30, 2017

Conversation

jbagga
Copy link
Contributor

@jbagga jbagga commented Aug 29, 2017

Sample code for aspnet/Mvc#6637

cc @rynowak @Eilon

@dnfclas
Copy link

dnfclas commented Aug 29, 2017

@jbagga,
Thanks for having already signed the Contribution License Agreement. Your agreement was validated by .NET Foundation. We will now review your pull request.
Thanks,
.NET Foundation Pull Request Bot

ControllerModels = new List<ControllerModel>();
}

public IList<ControllerModel> ControllerModels { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a local variable, there's no need for it to exist outside the scope of Apply

@@ -0,0 +1,34 @@
using System;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You seem to have two copies of the files:

samples/Mvc.ControllerForMultipleAreasSample/Startup.cs
samples/Mvc/Mvc.ControllerForMultipleAreasSample/Startup.cs


<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
</ItemGroup>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should look like our other projects in this repo, and use the latest bits

foreach (var controller in application.Controllers)
{
var areas = controller.ControllerType.GetCustomAttributes<MultipleAreasAttribute>().FirstOrDefault();
var areaNames = areas?.AreaNames;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be clearer if you just short circuited this entirely


namespace ControllerForMultipleAreasSample
{
public class MultipleAreasControllerConvention : IApplicationModelConvention
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also use IControllerModelConvention instead and then you don't need the loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How will the new copied controllers with different area value in its RouteValues be added to the application?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not explained here but we ran into a problem with this approach. You can't modify application.Controllers while inside an IControllerModelConvention.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MultipleAreasAttribute : Attribute
{
public MultipleAreasAttribute(string[] areaNames)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a handy pattern for these things is to do something like MulipleAreasAttribute(string a1, string a2, params string[] a3...) that makes it clear you're supposed to use at least 2 values.

var areas = controller.ControllerType.GetCustomAttributes<MultipleAreasAttribute>().FirstOrDefault();
var areaNames = areas?.AreaNames;

for (var i = 0; i < areaNames?.Length; i++)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a more common pattern for this is to just start the loop at 1. So move L28 outside of the loop, and then simplify the body to just L33-35


namespace ControllerForMultipleAreasSample
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this attribute can target only classes, right? Not methods?

AreaNames = areaNames;
}

public string[] AreaNames { get; private set; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably don't need private set since this is set only in the ctor.

@@ -0,0 +1,13 @@
using Microsoft.AspNetCore.Mvc;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add license headers to all the files too.

@jbagga jbagga force-pushed the jbagga/MultipleAreasControllerSample branch from af3176b to aa43965 Compare August 29, 2017 21:46
@jbagga
Copy link
Contributor Author

jbagga commented Aug 29, 2017

@Eilon @rynowak Updated


using Microsoft.AspNetCore.Mvc;

namespace ControllerForMultipleAreasSample.Areas.Products.Controllers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be clearer to put this somewhere else. This could just go in the root (file and namespace wise)

@@ -0,0 +1,31 @@
using System.Collections.Generic;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

license

@@ -0,0 +1 @@
Services View
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jbagga
Copy link
Contributor Author

jbagga commented Aug 29, 2017

@Eilon Updated

Copy link
Contributor

@Eilon Eilon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few tiny comments, plus I suggest adding a README.md to the folder of this sample that has a few short words about what this is (and even link back to the original issue that motivated creating this sample).

Here are a few examples of reasonably meaningful readmes for inspiration:

public MultipleAreasAttribute(string area1, string area2, params string[] areaNames)
{
AreaNames = new string[] { area1, area2 };
AreaNames = AreaNames.Concat(areaNames).ToArray();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can probably do both the above lines in 1 line of code.


foreach (var model in controllerModels)
{
application.Controllers.Add(model);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to do this within the inner nested loop above? That is, instead of making a list, then iterating over the list, why not just add each new model immediately?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because that modifies the collection (application.Controllers), which halts the enumeration (in the above for loop).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, obviously, thanks! 😄

@jbagga
Copy link
Contributor Author

jbagga commented Aug 30, 2017

@Eilon Added a README

Copy link
Contributor

@Eilon Eilon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@jbagga jbagga merged commit 431036a into dev Aug 30, 2017
@jbagga jbagga deleted the jbagga/MultipleAreasControllerSample branch August 30, 2017 21:34
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants