├── .gitignore ├── Controllers ├── ContentController.cs └── TagController.cs ├── LICENSE ├── Models ├── BaseModel.cs ├── Content.cs └── Tag.cs ├── MonkeyHubApi.csproj ├── Program.cs ├── README.md ├── Repositories ├── ContentRepository.cs └── TagRepository.cs ├── Startup.cs ├── appsettings.Development.json └── appsettings.json /.gitignore: -------------------------------------------------------------------------------- 1 | _build/ 2 | _site/ 3 | Properties/ 4 | node_modules/ 5 | wwwroot/ 6 | 7 | # Use git add -f to force override .sln when required. Not needed in most cases. 8 | # git add -f myProj.sln 9 | *.sln 10 | 11 | Project_Readme.html 12 | 13 | ## Ignore Visual Studio temporary files, build results, and 14 | ## files generated by popular Visual Studio add-ons. 15 | 16 | # User-specific files 17 | *.suo 18 | *.user 19 | *.userosscache 20 | *.sln.docstates 21 | *.vscode/ 22 | # User-specific files (MonoDevelop/Xamarin Studio) 23 | *.userprefs 24 | 25 | # Build results 26 | [Dd]ebug/ 27 | [Dd]ebugPublic/ 28 | [Rr]elease/ 29 | [Rr]eleases/ 30 | x64/ 31 | x86/ 32 | build/ 33 | bld/ 34 | [Bb]in/ 35 | [Oo]bj/ 36 | 37 | # Visual Studo 2015 cache/options directory 38 | .vs/ 39 | 40 | # MSTest test Results 41 | [Tt]est[Rr]esult*/ 42 | [Bb]uild[Ll]og.* 43 | 44 | # NUNIT 45 | *.VisualState.xml 46 | TestResult.xml 47 | 48 | # Build Results of an ATL Project 49 | [Dd]ebugPS/ 50 | [Rr]eleasePS/ 51 | dlldata.c 52 | 53 | *_i.c 54 | *_p.c 55 | *_i.h 56 | *.ilk 57 | *.meta 58 | *.obj 59 | *.pch 60 | *.pdb 61 | *.pgc 62 | *.pgd 63 | *.rsp 64 | *.sbr 65 | *.tlb 66 | *.tli 67 | *.tlh 68 | *.tmp 69 | *.tmp_proj 70 | *.log 71 | *.vspscc 72 | *.vssscc 73 | .builds 74 | *.pidb 75 | *.svclog 76 | *.scc 77 | 78 | # Chutzpah Test files 79 | _Chutzpah* 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # TFS 2012 Local Workspace 95 | $tf/ 96 | 97 | # Guidance Automation Toolkit 98 | *.gpState 99 | 100 | # ReSharper is a .NET coding add-in 101 | _ReSharper*/ 102 | *.[Rr]e[Ss]harper 103 | *.DotSettings.user 104 | 105 | # JustCode is a .NET coding addin-in 106 | .JustCode 107 | 108 | # TeamCity is a build add-in 109 | _TeamCity* 110 | 111 | # DotCover is a Code Coverage Tool 112 | *.dotCover 113 | 114 | # NCrunch 115 | _NCrunch_* 116 | .*crunch*.local.xml 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | *.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | 158 | # Windows Azure Build Output 159 | csx/ 160 | *.build.csdef 161 | 162 | # Windows Store app package directory 163 | AppPackages/ 164 | 165 | # Others 166 | *.[Cc]ache 167 | ClientBin/ 168 | [Ss]tyle[Cc]op.* 169 | ~$* 170 | *~ 171 | *.dbmdl 172 | *.dbproj.schemaview 173 | *.pfx 174 | *.publishsettings 175 | node_modules/ 176 | bower_components/ 177 | 178 | # RIA/Silverlight projects 179 | Generated_Code/ 180 | 181 | # Backup & report files from converting an old project file 182 | # to a newer Visual Studio version. Backup files are not needed, 183 | # because we have git ;-) 184 | _UpgradeReport_Files/ 185 | Backup*/ 186 | UpgradeLog*.XML 187 | UpgradeLog*.htm 188 | 189 | # SQL Server files 190 | *.mdf 191 | *.ldf 192 | 193 | # Business Intelligence projects 194 | *.rdl.data 195 | *.bim.layout 196 | *.bim_*.settings 197 | 198 | # Microsoft Fakes 199 | FakesAssemblies/ 200 | 201 | # Node.js Tools for Visual Studio 202 | .ntvs_analysis.dat 203 | 204 | # Visual Studio 6 build log 205 | *.plg 206 | 207 | # Visual Studio 6 workspace options file 208 | *.opt 209 | 210 | project.lock.json 211 | **/sample/**/wwwroot/lib/ 212 | **/samples/**/wwwroot/lib/ 213 | __pycache__/ 214 | 215 | #Mac OSX 216 | .DS_Store 217 | -------------------------------------------------------------------------------- /Controllers/ContentController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Mvc; 7 | using MonkeyHubApi.Models; 8 | using MonkeyHubApi.Repositories; 9 | 10 | namespace MonkeyHubApi.Controllers 11 | { 12 | 13 | [Route("api/[controller]")] 14 | [Produces("application/json")] 15 | public class ContentController : Controller 16 | { 17 | readonly IContentRepository _contentRepository; 18 | 19 | public ContentController(IContentRepository contentRepository) 20 | { 21 | _contentRepository = contentRepository; 22 | } 23 | 24 | // GET api/content 25 | [HttpGet] 26 | public async Task Get() 27 | { 28 | var contents = await _contentRepository.GetContentAsync(); 29 | return Ok(contents); 30 | } 31 | 32 | // GET api/content/id 33 | [HttpGet] 34 | [Route("id")] 35 | public async Task GetById([FromQuery] string id) 36 | { 37 | if (string.IsNullOrWhiteSpace(id)) return BadRequest(); 38 | var content = await _contentRepository.GetContentByIdAsync(id); 39 | if (content == null) return NotFound(); 40 | 41 | return Ok(content); 42 | } 43 | 44 | // GET api/content/tag 45 | [HttpGet] 46 | [Route("tag")] 47 | public async Task GetByTagId([FromQuery] string tag) 48 | { 49 | if (string.IsNullOrWhiteSpace(tag)) return BadRequest(); 50 | var contents = await _contentRepository.GetContentByTagIdAsync(tag); 51 | if (contents == null) return NotFound(); 52 | 53 | return Ok(contents); 54 | } 55 | 56 | // GET api/content/search 57 | [HttpGet] 58 | [Route("search")] 59 | public async Task Search([FromQuery] string filter) 60 | { 61 | if (string.IsNullOrWhiteSpace(filter)) return BadRequest(); 62 | var contents = await _contentRepository.SearchContentAsync(filter.ToLower()); 63 | if (contents == null) return NotFound(); 64 | 65 | return Ok(contents); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Controllers/TagController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using MonkeyHubApi.Models; 7 | using MonkeyHubApi.Repositories; 8 | 9 | namespace MonkeyHubApi.Controllers 10 | { 11 | [Route("api/[controller]")] 12 | [Produces("application/json")] 13 | public class TagsController : Controller 14 | { 15 | readonly ITagRepository _tagRepository; 16 | 17 | public TagsController(ITagRepository tagRepository) 18 | { 19 | _tagRepository = tagRepository; 20 | } 21 | 22 | // GET api/tags 23 | [HttpGet] 24 | public async Task Get() 25 | { 26 | var tags = await _tagRepository.GetTagAsync(); 27 | return Ok(tags); 28 | } 29 | 30 | // GET api/tag/id 31 | [HttpGet] 32 | [Route("id")] 33 | public async Task GetById([FromQuery] string id) 34 | { 35 | if (string.IsNullOrWhiteSpace(id)) return BadRequest(); 36 | var tag = await _tagRepository.GetTagByIdAsync(id); 37 | if (tag == null) return NotFound(); 38 | 39 | return Ok(tag); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Monkey Nights 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Models/BaseModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MonkeyHubApi.Models 4 | { 5 | public class BaseModel 6 | { 7 | public string Id { get; set; } 8 | 9 | public BaseModel() 10 | { 11 | Id = Guid.NewGuid().ToString(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Models/Content.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MonkeyHubApi.Models 4 | { 5 | /// 6 | /// Conteúdo 7 | /// 8 | public class Content : BaseModel 9 | { 10 | /// 11 | /// Obtém ou define o nome. 12 | /// 13 | /// O nome. 14 | public string Name { get; set; } 15 | 16 | /// 17 | /// Obtém ou define a descrição. 18 | /// 19 | /// A descrição. 20 | public string Description { get; set; } 21 | 22 | /// 23 | /// Obtém ou define a tag do conteúdo. 24 | /// 25 | /// A tag. 26 | public Tag Tag { get; set; } 27 | 28 | /// 29 | /// Obtém ou define a imagem de banner do conteúdo. 30 | /// 31 | /// O banner. 32 | public string Banner { get; set; } 33 | 34 | /// 35 | /// Obtém ou define a url conteúdo. 36 | /// 37 | /// A URL. 38 | public string Url { get; set; } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Models/Tag.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MonkeyHubApi.Models 4 | { 5 | /// 6 | /// Tag. 7 | /// 8 | public class Tag : BaseModel 9 | { 10 | /// 11 | /// Obtém ou define o nome. 12 | /// 13 | /// O nome. 14 | public string Name { get; set; } 15 | 16 | /// 17 | /// https://pt.wikipedia.org/wiki/Slug_(programa%C3%A7%C3%A3o) 18 | /// 19 | /// O Slug. 20 | public string Slug { get; set; } 21 | 22 | /// 23 | /// Obtém ou define a descrição 24 | /// 25 | /// A descrição. 26 | public string Description { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /MonkeyHubApi.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp1.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Builder; 7 | using Microsoft.AspNetCore.Hosting; 8 | 9 | namespace MonkeyHubApi 10 | { 11 | public class Program 12 | { 13 | public static void Main(string[] args) 14 | { 15 | var host = new WebHostBuilder() 16 | .UseKestrel() 17 | .UseContentRoot(Directory.GetCurrentDirectory()) 18 | .UseIISIntegration() 19 | .UseStartup() 20 | .Build(); 21 | 22 | host.Run(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # monkey-hub-api 2 | -------------------------------------------------------------------------------- /Repositories/ContentRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using MonkeyHubApi.Models; 5 | using System.Linq; 6 | 7 | namespace MonkeyHubApi.Repositories 8 | { 9 | public interface IContentRepository 10 | { 11 | Task> GetContentAsync(); 12 | Task GetContentByIdAsync(string id); 13 | Task> GetContentByTagIdAsync(string tagId); 14 | Task> SearchContentAsync(string filter); 15 | } 16 | 17 | public class ContentRepository : IContentRepository 18 | { 19 | 20 | #region [contents] 21 | List contents = new List 22 | { 23 | new Content { 24 | Id = "623d8b16-1192-11e7-93ae-92361f002671", 25 | Name = "Participe do Xamarin Summit 2017", 26 | Description="Nos dias 26 e 27 de Maio 2017 em São Paulo, vai rolar o maior encontro de desenvolvedores Xamarin da América Latina", 27 | Banner = "http://xamarinsummit.com.br/img/new_front.jpg", 28 | Url = "http://xamarinsummit.com.br/", 29 | Tag = new Tag { 30 | Id="480d4e42-1192-11e7-93ae-92361f002671", 31 | Name="Eventos", 32 | Description="Eventos da comunidade Xamarin no Brasil", 33 | Slug="eventos" 34 | } 35 | }, 36 | 37 | new Content { 38 | Id = "623d9084-1192-11e7-93ae-92361f002671", 39 | Name = "Resolvendo o problema ‘Deployment failed because of an internal error: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE]’", 40 | Description="Esse erro ocorreu pois eu compilei o app com uma versão do Xamarin Studio, atualizei a IDE, e tentei compilar novamente.", 41 | Banner = "http://res.cloudinary.com/https-xamarinbr-azurewebsites-net/image/upload/v1435031581/code-sharing-2_khe8vn.png", 42 | Url = "http://xamarinbr.azurewebsites.net/xamarin-android-resolvendo-o-problema-deployment-failed-because-of-an-internal-error-failure-install_failed_update_incompatible/", 43 | Tag = new Tag { 44 | Id="380d52a2-1192-11e7-93ae-92361f002671", 45 | Name="Xamarin Android", 46 | Description="Aqui você vai encontrar ajuda relacionada a Xamarin.Android,", 47 | Slug="xamarin-android" 48 | } 49 | }, 50 | 51 | new Content { 52 | Id = "623d9232-1192-11e7-93ae-92361f002671", 53 | Name = "Criando um App iOS usando o Visual Studio e Xamarin", 54 | Description="Eu preciso de um Mac para criar um app para iOS? Como eu faço para usar o Xamarin dentro do Visual Studio?", 55 | Banner = "http://res.cloudinary.com/https-xamarinbr-azurewebsites-net/image/upload/v1435031581/code-sharing-2_khe8vn.png", 56 | Url = "http://xamarinbr.azurewebsites.net/criando-um-app-ios-usando-o-visual-studio-e-xamarin/", 57 | Tag = new Tag { 58 | Id="280d52a2-1192-11e7-93ae-92361f002671", 59 | Name="Xamarin iOS", 60 | Description="Aqui você vai encontrar ajuda relacionada a Xamarin.iOS", 61 | Slug="xamarin-ios" 62 | } 63 | }, 64 | 65 | new Content { 66 | Id = "623d9232-1192-11e7-93ae-92361f002671", 67 | Name = "Tutorial: Facebook Login com Xamarin Forms", 68 | Description="Neste exemplo eu mostro como utilizar o login do Facebook com Xamarin Forms.", 69 | Banner = "http://frases-para-status.com/wp-content/uploads/2016/07/status-para-facebook-810x400.png", 70 | Url = "https://www.youtube.com/watch?v=cyq_ho4QflQ&index=9&list=PLNTCwkT5owTT0elAbegf6Akf1Mf0_HAbL", 71 | Tag = new Tag { 72 | Id="180d52a2-1192-11e7-93ae-92361f002671", 73 | Name="Xamarin.Forms", 74 | Description="Aqui você vai encontrar ajuda relacionada a Xamarin.Forms", 75 | Slug="xamarin-forms" 76 | } 77 | }, 78 | 79 | }; 80 | #endregion 81 | 82 | public async Task> GetContentAsync() 83 | { 84 | return await Task.FromResult(contents); 85 | } 86 | 87 | public async Task GetContentByIdAsync(string id) 88 | { 89 | return await Task.FromResult(contents.FirstOrDefault(c => c.Id.Equals(id))); 90 | } 91 | 92 | public async Task> GetContentByTagIdAsync(string tagId) 93 | { 94 | return await Task.FromResult(contents.Where(c => c.Tag.Id.Equals(tagId)).ToList()); 95 | } 96 | 97 | public async Task> SearchContentAsync(string filter) 98 | { 99 | return await Task.FromResult(contents 100 | .Where(c => c.Description.ToLower().Contains(filter) || c.Name.ToLower().Contains(filter)) 101 | .ToList()); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Repositories/TagRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using MonkeyHubApi.Models; 5 | using System.Linq; 6 | 7 | namespace MonkeyHubApi.Repositories 8 | { 9 | public interface ITagRepository 10 | { 11 | Task> GetTagAsync(); 12 | Task GetTagByIdAsync(string id); 13 | } 14 | 15 | public class TagRepository : ITagRepository 16 | { 17 | IContentRepository _contentRepository; 18 | 19 | public TagRepository(IContentRepository contentRepository) 20 | { 21 | _contentRepository = contentRepository; 22 | } 23 | 24 | public async Task> GetTagAsync() 25 | { 26 | var content = await _contentRepository.GetContentAsync(); 27 | return await Task.Run(() => content.Select(c => c.Tag).ToList()); 28 | } 29 | 30 | public async Task GetTagByIdAsync(string id) 31 | { 32 | var content = await _contentRepository.GetContentAsync(); 33 | return await Task.Run(() => content.Where(c => c.Tag.Id.Equals(id)).Select(c => c.Tag).FirstOrDefault()); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | using MonkeyHubApi.Repositories; 7 | using Swashbuckle.AspNetCore.Swagger; 8 | 9 | 10 | namespace MonkeyHubApi 11 | { 12 | public class Startup 13 | { 14 | public Startup(IHostingEnvironment env) 15 | { 16 | var builder = new ConfigurationBuilder() 17 | .SetBasePath(env.ContentRootPath) 18 | .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) 19 | .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) 20 | .AddEnvironmentVariables(); 21 | Configuration = builder.Build(); 22 | } 23 | 24 | public IConfigurationRoot Configuration { get; } 25 | 26 | // This method gets called by the runtime. Use this method to add services to the container. 27 | public void ConfigureServices(IServiceCollection services) 28 | { 29 | // Add framework services. 30 | services.AddMvc(); 31 | 32 | 33 | //IOC 34 | services.AddScoped(); 35 | services.AddScoped(); 36 | 37 | //Adding swagger generation with default settings 38 | services.AddSwaggerGen(options => 39 | { 40 | options.SwaggerDoc("v1", new Info 41 | { 42 | Title = "Monkey Hub API", 43 | Version = "v1", 44 | Description = "API do Monkey Hub, um centralizador de links para conteúdo (artigos, videos, tutoriais, exemplos de código) brasileiro sobre Xamarin em português." 45 | }); 46 | }); 47 | } 48 | 49 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 50 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 51 | { 52 | loggerFactory.AddConsole(Configuration.GetSection("Logging")); 53 | loggerFactory.AddDebug(); 54 | 55 | app.UseSwagger(); 56 | 57 | app.UseSwaggerUI(c => 58 | { 59 | c.SwaggerEndpoint("/swagger/v1/swagger.json", "Monkey Hub API"); 60 | }); 61 | 62 | app.UseMvc(); 63 | 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Debug", 6 | "System": "Information", 7 | "Microsoft": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Warning" 6 | } 7 | } 8 | } 9 | --------------------------------------------------------------------------------