public Metadata Generate()
        {
            var controllers = typeof(ControllerBase).Assembly.GetTypes()
                              .Where(t => !t.IsAbstract && typeof(ControllerBase).IsAssignableFrom(t)).ToArray();

            var services = new List <MetadataService>();

            foreach (var controller in controllers)
            {
                var methods = new List <MetadataMethod>();

                // inbound messages
                foreach (var action in controller.GetMethods(BindingFlags.Public | BindingFlags.Instance)
                         .Where(m => m.IsDefined(typeof(ActionAttribute), true)))
                {
                    var actionAttribute = action.GetCustomAttributes(typeof(ActionAttribute), true).Cast <ActionAttribute>().First();
                    methods.Add(new MetadataMethod
                    {
                        Name               = actionAttribute.ActionName,
                        Documentation      = _wsXmlCommentReader.GetMethodElement(action).ElementContents("summary"),
                        Originator         = IsDeviceMethod(action) ? "Device" : "Client",
                        Authorization      = GetAuthorization(action),
                        RequestParameters  = GetRequestParameters(action),
                        ResponseParameters = GetResponseParameters(action, actionAttribute.ActionName),
                    });
                }

                // outbound messages
                foreach (var action in controller.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
                {
                    var methodElement = _wsXmlCommentReader.GetMethodElement(action);
                    var actionElement = methodElement == null ? null : methodElement.Element("action");
                    if (actionElement == null)
                    {
                        continue;
                    }

                    methods.Add(new MetadataMethod
                    {
                        Name               = "srv: " + actionElement.Contents(),
                        Documentation      = methodElement.ElementContents("summary"),
                        Originator         = "Server",
                        Authorization      = "n/a",
                        ResponseParameters = GetResponseParameters(action, actionElement.Contents()),
                    });
                }

                services.Add(new MetadataService
                {
                    Name          = controller.Name.Replace("Controller", ""),
                    Uri           = "/" + controller.Name.Replace("Controller", "").ToLower(),
                    Documentation = _wsXmlCommentReader.GetTypeElement(controller).ElementContents("summary"),
                    Methods       = methods.OrderBy(m => m.Name).ToArray(),
                });
            }
            var metadata = new Metadata {
                Services = services.ToArray()
            };

            return(metadata);
        }