├── .gitattributes ├── .gitignore ├── .vs └── config │ └── applicationhost.config ├── MyCountries.Web ├── .bowerrc ├── Api │ └── VisitController.cs ├── Controllers │ ├── AccountController.cs │ ├── HomeController.cs │ ├── ManageController.cs │ ├── MyController.cs │ ├── TemplatesController.cs │ └── UserController.cs ├── Data │ ├── IMyCountriesRepository.cs │ ├── MyCountriesContext.cs │ ├── MyCountriesRepository.cs │ ├── SampleDataInitializer.cs │ └── Visit.cs ├── Hacks │ └── Countries.cs ├── Helpers │ └── UrlHelperExtensions.cs ├── Migrations │ ├── 20151015230214_InitialDatabase.Designer.cs │ ├── 20151015230214_InitialDatabase.cs │ └── MyCountriesContextModelSnapshot.cs ├── Models │ ├── ApplicationUser.cs │ └── ContactModel.cs ├── MyCountries.Web.xproj ├── Properties │ ├── Assembly.cs │ └── launchSettings.json ├── Services │ ├── IEmailSender.cs │ ├── ISmsSender.cs │ └── MessageServices.cs ├── Startup.cs ├── ViewModels │ ├── Account │ │ ├── ExternalLoginConfirmationViewModel.cs │ │ ├── ForgotPasswordViewModel.cs │ │ ├── LoginViewModel.cs │ │ ├── RegisterViewModel.cs │ │ ├── ResetPasswordViewModel.cs │ │ ├── SendCodeViewModel.cs │ │ └── VerifyCodeViewModel.cs │ └── Manage │ │ ├── AddPhoneNumberViewModel.cs │ │ ├── ChangePasswordViewModel.cs │ │ ├── ConfigureTwoFactorViewModel.cs │ │ ├── FactorViewModel.cs │ │ ├── IndexViewModel.cs │ │ ├── ManageLoginsViewModel.cs │ │ ├── SetPasswordViewModel.cs │ │ └── VerifyPhoneNumberViewModel.cs ├── Views │ ├── Account │ │ ├── ConfirmEmail.cshtml │ │ ├── ExternalLoginConfirmation.cshtml │ │ ├── ExternalLoginFailure.cshtml │ │ ├── ForgotPassword.cshtml │ │ ├── ForgotPasswordConfirmation.cshtml │ │ ├── Lockout.cshtml │ │ ├── Login.cshtml │ │ ├── Register.cshtml │ │ ├── ResetPassword.cshtml │ │ ├── ResetPasswordConfirmation.cshtml │ │ ├── SendCode.cshtml │ │ └── VerifyCode.cshtml │ ├── Home │ │ ├── About.cshtml │ │ ├── Contact.cshtml │ │ └── Index.cshtml │ ├── Manage │ │ ├── AddPhoneNumber.cshtml │ │ ├── ChangePassword.cshtml │ │ ├── Index.cshtml │ │ ├── ManageLogins.cshtml │ │ ├── RemoveLogin.cshtml │ │ ├── SetPassword.cshtml │ │ └── VerifyPhoneNumber.cshtml │ ├── My │ │ └── Index.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ ├── _Layout.cshtml │ │ ├── _LoginPartial.cshtml │ │ ├── _Nav.cshtml │ │ ├── _ValidationScriptsPartial.cshtml │ │ └── _about.cshtml │ ├── Templates │ │ ├── _ViewStart.cshtml │ │ ├── editVisit.cshtml │ │ ├── myVisits.cshtml │ │ └── newVisit.cshtml │ ├── User │ │ └── Visits.cshtml │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── bower.json ├── config.json ├── gulpfile.js ├── hosting.ini ├── package.json ├── project.json ├── project.lock.json └── wwwroot │ ├── _references.js │ ├── css │ └── site.css │ ├── img │ ├── flags │ │ ├── Afghanistan.png │ │ ├── Albania.png │ │ ├── Algeria.png │ │ ├── American_Samoa.png │ │ ├── Andorra.png │ │ ├── Angola.png │ │ ├── Anguilla.png │ │ ├── Antigua_and_Barbuda.png │ │ ├── Argentina.png │ │ ├── Armenia.png │ │ ├── Aruba.png │ │ ├── Australia.png │ │ ├── Austria.png │ │ ├── Azerbaijan.png │ │ ├── Bahamas.png │ │ ├── Bahrain.png │ │ ├── Bangladesh.png │ │ ├── Barbados.png │ │ ├── Belarus.png │ │ ├── Belgium.png │ │ ├── Belize.png │ │ ├── Benin.png │ │ ├── Bermuda.png │ │ ├── Bhutan.png │ │ ├── Bolivia.png │ │ ├── Bosnia.png │ │ ├── Botswana.png │ │ ├── Brazil.png │ │ ├── British_Virgin_Islands.png │ │ ├── Brunei.png │ │ ├── Bulgaria.png │ │ ├── Burkina_Faso.png │ │ ├── Burundi.png │ │ ├── Cambodia.png │ │ ├── Cameroon.png │ │ ├── Canada.png │ │ ├── Cape_Verde.png │ │ ├── Cayman_Islands.png │ │ ├── Central_African_Republic.png │ │ ├── Chad.png │ │ ├── Chile.png │ │ ├── China.png │ │ ├── Christmas_Island.png │ │ ├── Colombia.png │ │ ├── Comoros.png │ │ ├── Cook_Islands.png │ │ ├── Costa_Rica.png │ │ ├── Croatia.png │ │ ├── Cuba.png │ │ ├── Cyprus.png │ │ ├── Czech_Republic.png │ │ ├── Côte_d'Ivoire.png │ │ ├── Democratic_Republic_of_the_Congo.png │ │ ├── Denmark.png │ │ ├── Djibouti.png │ │ ├── Dominica.png │ │ ├── Dominican_Republic.png │ │ ├── Ecuador.png │ │ ├── Egypt.png │ │ ├── El_Salvador.png │ │ ├── Equatorial_Guinea.png │ │ ├── Eritrea.png │ │ ├── Estonia.png │ │ ├── Ethiopia.png │ │ ├── Falkland_Islands.png │ │ ├── Faroe_Islands.png │ │ ├── Fiji.png │ │ ├── Finland.png │ │ ├── France.png │ │ ├── French_Polynesia.png │ │ ├── Gabon.png │ │ ├── Gambia.png │ │ ├── Georgia.png │ │ ├── Germany.png │ │ ├── Ghana.png │ │ ├── Gibraltar.png │ │ ├── Greece.png │ │ ├── Greenland.png │ │ ├── Grenada.png │ │ ├── Guam.png │ │ ├── Guatemala.png │ │ ├── Guinea.png │ │ ├── Guinea_Bissau.png │ │ ├── Guyana.png │ │ ├── Haiti.png │ │ ├── Honduras.png │ │ ├── Hong_Kong.png │ │ ├── Hungary.png │ │ ├── Iceland.png │ │ ├── India.png │ │ ├── Indonesia.png │ │ ├── Iran.png │ │ ├── Iraq.png │ │ ├── Ireland.png │ │ ├── Israel.png │ │ ├── Italy.png │ │ ├── Jamaica.png │ │ ├── Japan.png │ │ ├── Jordan.png │ │ ├── Kazakhstan.png │ │ ├── Kenya.png │ │ ├── Kiribati.png │ │ ├── Kuwait.png │ │ ├── Kyrgyzstan.png │ │ ├── Laos.png │ │ ├── Latvia.png │ │ ├── Lebanon.png │ │ ├── Lesotho.png │ │ ├── Liberia.png │ │ ├── Libya.png │ │ ├── Liechtenstein.png │ │ ├── Lithuania.png │ │ ├── Luxembourg.png │ │ ├── Macao.png │ │ ├── Macedonia.png │ │ ├── Madagascar.png │ │ ├── Malawi.png │ │ ├── Malaysia.png │ │ ├── Maldives.png │ │ ├── Mali.png │ │ ├── Malta.png │ │ ├── Marshall_Islands.png │ │ ├── Martinique.png │ │ ├── Mauritania.png │ │ ├── Mauritius.png │ │ ├── Mexico.png │ │ ├── Micronesia.png │ │ ├── Moldova.png │ │ ├── Monaco.png │ │ ├── Mongolia.png │ │ ├── Montserrat.png │ │ ├── Morocco.png │ │ ├── Mozambique.png │ │ ├── Myanmar.png │ │ ├── Namibia.png │ │ ├── Nauru.png │ │ ├── Nepal.png │ │ ├── Netherlands.png │ │ ├── Netherlands_Antilles.png │ │ ├── New_Zealand.png │ │ ├── Nicaragua.png │ │ ├── Niger.png │ │ ├── Nigeria.png │ │ ├── Niue.png │ │ ├── Norfolk_Island.png │ │ ├── North_Korea.png │ │ ├── Norway.png │ │ ├── Oman.png │ │ ├── Pakistan.png │ │ ├── Palau.png │ │ ├── Panama.png │ │ ├── Papua_New_Guinea.png │ │ ├── Paraguay.png │ │ ├── Peru.png │ │ ├── Philippines.png │ │ ├── Pitcairn_Islands.png │ │ ├── Poland.png │ │ ├── Portugal.png │ │ ├── Puerto_Rico.png │ │ ├── Qatar.png │ │ ├── Republic_of_the_Congo.png │ │ ├── Romania.png │ │ ├── Russian_Federation.png │ │ ├── Rwanda.png │ │ ├── Saint_Kitts_and_Nevis.png │ │ ├── Saint_Lucia.png │ │ ├── Saint_Pierre.png │ │ ├── Saint_Vicent_and_the_Grenadines.png │ │ ├── Samoa.png │ │ ├── San_Marino.png │ │ ├── Sao_Tomé_and_Príncipe.png │ │ ├── Saudi_Arabia.png │ │ ├── Senegal.png │ │ ├── Serbia_and_Montenegro.png │ │ ├── Seychelles.png │ │ ├── Sierra_Leone.png │ │ ├── Singapore.png │ │ ├── Slovakia.png │ │ ├── Slovenia.png │ │ ├── Soloman_Islands.png │ │ ├── Somalia.png │ │ ├── South_Africa.png │ │ ├── South_Georgia.png │ │ ├── South_Korea.png │ │ ├── Soviet_Union.png │ │ ├── Spain.png │ │ ├── Sri_Lanka.png │ │ ├── Sudan.png │ │ ├── Suriname.png │ │ ├── Swaziland.png │ │ ├── Sweden.png │ │ ├── Switzerland.png │ │ ├── Syria.png │ │ ├── Taiwan.png │ │ ├── Tajikistan.png │ │ ├── Tanzania.png │ │ ├── Thailand.png │ │ ├── Tibet.png │ │ ├── Timor-Leste.png │ │ ├── Togo.png │ │ ├── Tonga.png │ │ ├── Trinidad_and_Tobago.png │ │ ├── Tunisia.png │ │ ├── Turkey.png │ │ ├── Turkmenistan.png │ │ ├── Turks_and_Caicos_Islands.png │ │ ├── Tuvalu.png │ │ ├── UAE.png │ │ ├── US_Virgin_Islands.png │ │ ├── Uganda.png │ │ ├── Ukraine.png │ │ ├── United_Kingdom.png │ │ ├── United_States_of_America.png │ │ ├── Uruguay.png │ │ ├── Uzbekistan.png │ │ ├── Vanuatu.png │ │ ├── Vatican_City.png │ │ ├── Venezuela.png │ │ ├── Vietnam.png │ │ ├── Wallis_and_Futuna.png │ │ ├── Yemen.png │ │ ├── Zambia.png │ │ └── Zimbabwe.png │ └── progress.gif │ ├── js │ ├── myApp-controllers.js │ ├── myApp.js │ └── mycountries-common.js │ ├── theme │ ├── 0-base.html │ ├── aboutus.html │ ├── assets │ │ ├── arrow_large_left.png │ │ ├── arrow_large_right.png │ │ ├── arrow_left.png │ │ ├── arrow_left2.png │ │ ├── arrow_right.png │ │ ├── arrow_right2.png │ │ ├── arrowleft.png │ │ ├── arrowright.png │ │ ├── arrows.psd │ │ ├── black50.png │ │ ├── boxed_bgtile.png │ │ ├── bullet.png │ │ ├── bullet_boxed.png │ │ ├── bullets.png │ │ ├── bullets.psd │ │ ├── bullets2.png │ │ ├── coloredbg.png │ │ ├── grain.png │ │ ├── large_left.png │ │ ├── large_right.png │ │ ├── loader.gif │ │ ├── loader2.gif │ │ ├── navigdots.png │ │ ├── navigdots_bgtile.png │ │ ├── shadow1.png │ │ ├── shadow2.png │ │ ├── shadow3.png │ │ ├── small_arrows.psd │ │ ├── small_left.png │ │ ├── small_left_boxed.png │ │ ├── small_right.png │ │ ├── small_right_boxed.png │ │ ├── timer.png │ │ ├── timerdot.png │ │ ├── transparent.jpg │ │ └── white50.png │ ├── blog-single.html │ ├── blog.html │ ├── careers.html │ ├── coming-soon.html │ ├── contact.html │ ├── css │ │ ├── animate.min.css │ │ ├── bootstrap.css │ │ ├── bootstrap.min.css │ │ ├── font-awesome.min.css │ │ ├── ie-style.css │ │ ├── jquery.countdown.css │ │ ├── prettyPhoto.css │ │ ├── settings-ie8.css │ │ ├── settings.css │ │ └── style.css │ ├── error.html │ ├── faq.html │ ├── feature.html │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ └── fontawesome-webfont.woff │ ├── gallery.html │ ├── img │ │ ├── c1.jpg │ │ ├── c2.jpg │ │ ├── c3.jpg │ │ ├── c4.jpg │ │ ├── c5.jpg │ │ ├── c6.jpg │ │ ├── c7.jpg │ │ ├── flat-icon │ │ │ ├── fi1.png │ │ │ ├── fi10.png │ │ │ ├── fi11.png │ │ │ ├── fi12.png │ │ │ ├── fi13.png │ │ │ ├── fi2.png │ │ │ ├── fi3.png │ │ │ ├── fi4.png │ │ │ ├── fi5.png │ │ │ ├── fi6.png │ │ │ ├── fi7.png │ │ │ ├── fi8.png │ │ │ └── fi9.png │ │ ├── grid-wall │ │ │ ├── wall01.jpg │ │ │ ├── wall02.jpg │ │ │ ├── wall03.jpg │ │ │ ├── wall04.jpg │ │ │ ├── wall05.jpg │ │ │ ├── wall06.jpg │ │ │ ├── wall07.jpg │ │ │ ├── wall08.jpg │ │ │ ├── wall09.jpg │ │ │ ├── wall10.jpg │ │ │ ├── wall11.jpg │ │ │ ├── wall12.jpg │ │ │ ├── wall13.jpg │ │ │ ├── wall14.jpg │ │ │ └── wall15.jpg │ │ ├── map.png │ │ ├── nav1.jpg │ │ ├── portfolio │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ ├── 4.jpg │ │ │ ├── 5.jpg │ │ │ ├── 6.jpg │ │ │ ├── 7.jpg │ │ │ ├── 8.jpg │ │ │ ├── 9.jpg │ │ │ ├── tn1.jpg │ │ │ ├── tn2.jpg │ │ │ ├── tn3.jpg │ │ │ ├── tn4.jpg │ │ │ ├── tn5.jpg │ │ │ ├── tn6.jpg │ │ │ ├── tn7.jpg │ │ │ ├── tn8.jpg │ │ │ └── tn9.jpg │ │ ├── prettyPhoto │ │ │ ├── dark_rounded │ │ │ │ ├── btnNext.png │ │ │ │ ├── btnPrevious.png │ │ │ │ ├── contentPattern.png │ │ │ │ ├── default_thumbnail.gif │ │ │ │ ├── loader.gif │ │ │ │ └── sprite.png │ │ │ ├── dark_square │ │ │ │ ├── btnNext.png │ │ │ │ ├── btnPrevious.png │ │ │ │ ├── contentPattern.png │ │ │ │ ├── default_thumbnail.gif │ │ │ │ ├── loader.gif │ │ │ │ └── sprite.png │ │ │ ├── default │ │ │ │ ├── default_thumb.png │ │ │ │ ├── loader.gif │ │ │ │ ├── sprite.png │ │ │ │ ├── sprite_next.png │ │ │ │ ├── sprite_prev.png │ │ │ │ ├── sprite_x.png │ │ │ │ └── sprite_y.png │ │ │ ├── facebook │ │ │ │ ├── btnNext.png │ │ │ │ ├── btnPrevious.png │ │ │ │ ├── contentPatternBottom.png │ │ │ │ ├── contentPatternLeft.png │ │ │ │ ├── contentPatternRight.png │ │ │ │ ├── contentPatternTop.png │ │ │ │ ├── default_thumbnail.gif │ │ │ │ ├── loader.gif │ │ │ │ └── sprite.png │ │ │ ├── light_rounded │ │ │ │ ├── btnNext.png │ │ │ │ ├── btnPrevious.png │ │ │ │ ├── default_thumbnail.gif │ │ │ │ ├── loader.gif │ │ │ │ └── sprite.png │ │ │ └── light_square │ │ │ │ ├── btnNext.png │ │ │ │ ├── btnPrevious.png │ │ │ │ ├── default_thumbnail.gif │ │ │ │ ├── loader.gif │ │ │ │ └── sprite.png │ │ ├── responsive.png │ │ ├── slider │ │ │ ├── logo.png │ │ │ ├── s21.png │ │ │ ├── s31.png │ │ │ ├── s32.png │ │ │ ├── s33.png │ │ │ ├── s34.png │ │ │ ├── slide1.jpg │ │ │ ├── slide2.jpg │ │ │ └── slide3.jpg │ │ ├── transparent-md.png │ │ ├── ui.totop.png │ │ ├── user.jpg │ │ ├── user2.jpg │ │ ├── w1.jpg │ │ ├── w2.jpg │ │ └── w3.jpg │ ├── index-column.html │ ├── index.html │ ├── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ ├── custom.js │ │ ├── excanvas.min.js │ │ ├── html5shiv.js │ │ ├── imagesloaded.pkgd.min.js │ │ ├── isotope.js │ │ ├── jquery.countTo.js │ │ ├── jquery.countdown.min.js │ │ ├── jquery.cycle.all.js │ │ ├── jquery.flot.min.js │ │ ├── jquery.flot.resize.min.js │ │ ├── jquery.js │ │ ├── jquery.prettyPhoto.js │ │ ├── jquery.themepunch.plugins.min.js │ │ ├── jquery.themepunch.revolution.min.js │ │ ├── masonry.pkgd.min.js │ │ ├── respond.min.js │ │ └── waypoints.min.js │ ├── landing-page.html │ ├── login.html │ ├── portfolio.html │ ├── pricing.html │ ├── product.html │ ├── resume.html │ ├── service.html │ ├── sitemap.html │ ├── testimonial.html │ └── time-line.html │ └── web.config ├── MyCountries.sln ├── README.md └── screenshot.jpg /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /MyCountries.Web/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "wwwroot/lib" 3 | } 4 | -------------------------------------------------------------------------------- /MyCountries.Web/Api/VisitController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNet.Mvc; 2 | using MyCountries.Web.Data; 3 | using System.Threading.Tasks; 4 | using System.Security.Principal; 5 | using System.Net; 6 | using System; 7 | using Microsoft.AspNet.Authorization; 8 | 9 | namespace MyCountries.Web.Api 10 | { 11 | [Authorize] 12 | [Route("api/visits")] 13 | public class VisitsController : Controller 14 | { 15 | private IMyCountriesRepository _repository; 16 | public VisitsController(IMyCountriesRepository repository) 17 | { 18 | _repository = repository; 19 | } 20 | 21 | [HttpGet("")] 22 | public async Task Get() 23 | { 24 | var username = User.Identity.Name; 25 | var results = await _repository.GetVisitsByUserNameAsync(username); 26 | 27 | return Json(results); 28 | } 29 | 30 | [HttpPost("")] 31 | public async Task Post([FromBody] Visit newVisit) 32 | { 33 | var username = User.Identity.Name; 34 | 35 | newVisit.UserName = username; 36 | 37 | if (await _repository.AddVisitAsync(newVisit)) 38 | { 39 | Response.StatusCode = (int)HttpStatusCode.Created; 40 | // TODO Fix for full path, Request doesn't include full request URI for some reason 41 | var location = string.Concat("/api/visits/", newVisit.Id); 42 | Response.Headers["location"] = location.ToString(); 43 | 44 | return Json(newVisit); 45 | } 46 | 47 | return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest); 48 | } 49 | 50 | [HttpPut("{id}")] 51 | public async Task Put(int id, [FromBody] Visit visit) 52 | { 53 | var currentUserName = User.Identity.Name; 54 | 55 | // Valid User Updating 56 | if (visit.UserName != currentUserName) 57 | { 58 | return new HttpStatusCodeResult((int)HttpStatusCode.Unauthorized); 59 | } 60 | 61 | if (await _repository.UpdateVisitAsync(visit)) 62 | { 63 | Response.StatusCode = (int)HttpStatusCode.OK; 64 | return Json(visit); 65 | } 66 | 67 | return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest); 68 | } 69 | 70 | [HttpDelete("{id}")] 71 | public async Task Delete(int id) 72 | { 73 | var currentUserName = User.Identity.Name; 74 | 75 | var visit = await _repository.GetVisitByIdAsync(id); 76 | 77 | // Valid User Updating 78 | if (visit.UserName != currentUserName) 79 | { 80 | return new HttpStatusCodeResult((int)HttpStatusCode.Unauthorized); 81 | } 82 | 83 | if (await _repository.DeleteVisitAsync(id)) 84 | { 85 | Response.StatusCode = (int)HttpStatusCode.OK; 86 | return Json(new { success = true }); 87 | } 88 | 89 | return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest); 90 | } 91 | 92 | 93 | [AllowAnonymous] 94 | [HttpGet("latest")] 95 | public async Task GetLatest() 96 | { 97 | return Json(await _repository.GetLatestVisits(5)); 98 | } 99 | 100 | 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /MyCountries.Web/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNet.Mvc; 6 | using MyCountries.Web.Data; 7 | using MyCountries.Web.Models; 8 | using MyCountries.Web.Services; 9 | 10 | namespace MyCountries.Web.Controllers 11 | { 12 | public class HomeController : Controller 13 | { 14 | private IEmailSender _emailer; 15 | public HomeController(IEmailSender emailer) 16 | { 17 | _emailer = emailer; 18 | } 19 | 20 | public ActionResult Index() 21 | { 22 | ViewBag.Message = "An example of ASP.NET 5"; 23 | 24 | return View(); 25 | } 26 | 27 | public IActionResult About() 28 | { 29 | ViewBag.Message = "An example of ASP.NET 5"; 30 | 31 | return View(); 32 | } 33 | 34 | public IActionResult Contact() 35 | { 36 | ViewBag.Message = "Your contact page."; 37 | 38 | return View(); 39 | } 40 | 41 | [HttpPost] 42 | public async Task Contact(ContactModel model) 43 | { 44 | ViewBag.Message = "Let us know what you think!"; 45 | 46 | if (ModelState.IsValid) 47 | { 48 | try 49 | { 50 | await _emailer.SendEmailAsync("shawn@wildermuth.com", "Message From MyCountries.io", 51 | string.Format(@"From: {1} ({2}){0}Comment: {3}", 52 | Environment.NewLine, 53 | model.Name, 54 | model.Email, 55 | model.Comments)); 56 | 57 | ModelState.Clear(); 58 | ViewBag.Result = "Message Sent"; 59 | } 60 | catch 61 | { 62 | ModelState.AddModelError("", "Failed to send email. Please try again later. The error was logged."); 63 | } 64 | } 65 | 66 | return View(); 67 | } 68 | 69 | 70 | public IActionResult Error(int id) 71 | { 72 | ViewBag.ErrorCode = id; 73 | 74 | return View("~/Views/Shared/Error.cshtml"); 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /MyCountries.Web/Controllers/MyController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNet.Mvc; 2 | using MyCountries.Web.Data; 3 | using System; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNet.Authorization; 6 | 7 | namespace MyCountries.Web.Controllers 8 | { 9 | [Authorize] 10 | public class MyController : Controller 11 | { 12 | private IMyCountriesRepository _repository; 13 | public MyController(IMyCountriesRepository repository) 14 | { 15 | _repository = repository; 16 | } 17 | 18 | public ActionResult Index() 19 | { 20 | return View(); 21 | } 22 | 23 | } 24 | } -------------------------------------------------------------------------------- /MyCountries.Web/Controllers/TemplatesController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNet.Mvc; 2 | using Microsoft.AspNet.Mvc.Rendering; 3 | using System; 4 | using System.Linq; 5 | using System.Collections.Generic; 6 | 7 | namespace MyCountries.Web.Controllers 8 | { 9 | public class TemplatesController : Controller 10 | { 11 | private List _selectCountriesList; 12 | public TemplatesController() 13 | { 14 | _selectCountriesList = ISO3166.Country.List.Select(c => new SelectListItem() { Text = c.Name }).ToList(); 15 | } 16 | 17 | public ActionResult NewVisit() 18 | { 19 | ViewBag.Countries = _selectCountriesList; 20 | return View(); 21 | } 22 | 23 | public ActionResult EditVisit() 24 | { 25 | ViewBag.Countries = _selectCountriesList; 26 | return View(); 27 | } 28 | 29 | public ActionResult MyVisits() 30 | { 31 | return View(); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /MyCountries.Web/Controllers/UserController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNet.Mvc; 2 | using Microsoft.AspNet.Identity; 3 | using MyCountries.Web.Data; 4 | using System.Threading.Tasks; 5 | using MyCountries.Web.Models; 6 | 7 | // For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 8 | 9 | namespace MyCountries.Web.Controllers 10 | { 11 | [Route("user")] 12 | public class UserController : Controller 13 | { 14 | private IMyCountriesRepository _repository; 15 | private UserManager _userManager; 16 | 17 | public UserController(IMyCountriesRepository repository, UserManager userManager) 18 | { 19 | _repository = repository; 20 | _userManager = userManager; 21 | } 22 | 23 | [HttpGet("{username}", Name = "UserVisits")] 24 | public async Task Visits(string username) 25 | { 26 | var user = await _userManager.FindByNameAsync(username); 27 | if (user == null) 28 | { 29 | return RedirectToAction("Index", "Home"); 30 | } 31 | 32 | var visits = await _repository.GetVisitsByUserNameAsync(username); 33 | 34 | return View(visits); 35 | } 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /MyCountries.Web/Data/IMyCountriesRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace MyCountries.Web.Data 5 | { 6 | public interface IMyCountriesRepository 7 | { 8 | Task> GetLatestVisits(int number); 9 | Task> GetVisitsByUserNameAsync(string username); 10 | Task AddVisitAsync(Visit newVisit); 11 | Task UpdateVisitAsync(Visit visit); 12 | Task GetVisitByIdAsync(int id); 13 | Task DeleteVisitAsync(int id); 14 | } 15 | } -------------------------------------------------------------------------------- /MyCountries.Web/Data/MyCountriesContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNet.Identity.EntityFramework; 2 | using Microsoft.Data.Entity; 3 | using Microsoft.Data.Entity.Metadata; 4 | using MyCountries.Web.Models; 5 | 6 | namespace MyCountries.Web.Data 7 | { 8 | public class MyCountriesContext : IdentityDbContext 9 | { 10 | public MyCountriesContext() 11 | { 12 | Database.EnsureCreated(); 13 | } 14 | 15 | public DbSet Visits { get; set; } 16 | 17 | protected override void OnModelCreating(ModelBuilder builder) 18 | { 19 | builder.Entity().HasKey(v => v.Id); 20 | 21 | base.OnModelCreating(builder); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /MyCountries.Web/Data/MyCountriesRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.Data.Entity; 6 | 7 | namespace MyCountries.Web.Data 8 | { 9 | public class MyCountriesRepository : IMyCountriesRepository 10 | { 11 | private MyCountriesContext _context; 12 | public MyCountriesRepository(MyCountriesContext context) 13 | { 14 | _context = context; 15 | } 16 | 17 | public async Task> GetVisitsByUserNameAsync(string username) 18 | { 19 | var lowerUserName = username.ToLowerInvariant(); 20 | 21 | return await _context.Visits 22 | .Where(v => v.UserName.ToLowerInvariant() == lowerUserName) 23 | .OrderBy(v => v.VisitDate) 24 | .ToListAsync(); 25 | } 26 | 27 | public async Task> GetLatestVisits(int number) 28 | { 29 | return await _context.Visits 30 | .OrderByDescending(v => v.VisitDate) 31 | .Take(number) 32 | .ToListAsync(); 33 | } 34 | 35 | public async Task AddVisitAsync(Visit newVisit) 36 | { 37 | _context.Visits.Add(newVisit); 38 | 39 | return (await _context.SaveChangesAsync() > 0); 40 | } 41 | 42 | public async Task UpdateVisitAsync(Visit visit) 43 | { 44 | _context.Visits.Update(visit); 45 | 46 | return (await _context.SaveChangesAsync() > 0); 47 | } 48 | 49 | public async Task GetVisitByIdAsync(int id) 50 | { 51 | return await _context.Visits 52 | .Where(v => v.Id == id) 53 | .FirstOrDefaultAsync(); 54 | } 55 | 56 | public async Task DeleteVisitAsync(int id) 57 | { 58 | var visit = await GetVisitByIdAsync(id); 59 | 60 | if (visit == null) return false; 61 | 62 | _context.Visits.Remove(visit); 63 | 64 | return (await _context.SaveChangesAsync() > 0); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /MyCountries.Web/Data/SampleDataInitializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Security.Claims; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNet.Identity; 6 | using MyCountries.Web.Models; 7 | 8 | namespace MyCountries.Web.Data 9 | { 10 | public class SampleDataInitializer 11 | { 12 | private MyCountriesContext _ctx; 13 | 14 | public SampleDataInitializer(MyCountriesContext ctx) 15 | { 16 | _ctx = ctx; 17 | } 18 | 19 | public void InitializeData() 20 | { 21 | CreateVisits(); 22 | } 23 | 24 | private void CreateVisits() 25 | { 26 | if (!_ctx.Visits.Any()) 27 | { 28 | _ctx.Visits.Add(new Visit() 29 | { 30 | Id = 0, 31 | UserName = "shawn@wildermuth.com", 32 | Country = "France", 33 | City = "Paris", 34 | VisitDate = new DateTime(2014, 6, 4), 35 | Duration = 31, 36 | Notes = "Start of our round-the-world trip", 37 | ForWork = false, 38 | ForFun = true 39 | }); 40 | 41 | _ctx.Visits.Add(new Visit() 42 | { 43 | Id = 0, 44 | UserName = "shawn@wildermuth.com", 45 | Country = "United Kingdom", 46 | City = "London", 47 | VisitDate = new DateTime(2014, 7, 2), 48 | Duration = 28, 49 | Notes = "Our visit to the UK", 50 | ForWork = true, 51 | ForFun = true 52 | }); 53 | 54 | _ctx.Visits.Add(new Visit() 55 | { 56 | Id = 0, 57 | UserName = "shawn@wildermuth.com", 58 | Country = "France", 59 | City = "Paris", 60 | VisitDate = new DateTime(2014, 6, 4), 61 | Duration = 31, 62 | Notes = "Start of our round-the-world trip", 63 | ForWork = false, 64 | ForFun = true 65 | }); 66 | 67 | _ctx.Visits.Add(new Visit() 68 | { 69 | Id = 0, 70 | UserName = "shawn@wildermuth.com", 71 | Country = "France", 72 | City = "Paris", 73 | VisitDate = new DateTime(2014, 6, 4), 74 | Duration = 31, 75 | Notes = "Start of our round-the-world trip", 76 | ForWork = false, 77 | ForFun = true 78 | }); 79 | 80 | _ctx.SaveChanges(); 81 | 82 | } 83 | } 84 | 85 | } 86 | } -------------------------------------------------------------------------------- /MyCountries.Web/Data/Visit.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MyCountries.Web.Data 4 | { 5 | public class Visit 6 | { 7 | public int Id { get; set; } 8 | public string Country { get; set; } 9 | public string City { get; set; } 10 | public DateTime VisitDate { get; set; } 11 | public bool ForWork { get; set; } 12 | public bool ForFun { get; set; } 13 | public string Notes { get; set; } 14 | public int Duration { get; set; } 15 | public bool FirstVisit { get; set; } 16 | 17 | public virtual string UserName { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /MyCountries.Web/Helpers/UrlHelperExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNet.Http; 2 | using Microsoft.AspNet.Mvc; 3 | using System; 4 | 5 | namespace MyCountries.Web.Helpers 6 | { 7 | } -------------------------------------------------------------------------------- /MyCountries.Web/Models/ApplicationUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNet.Identity; 2 | using Microsoft.AspNet.Identity.EntityFramework; 3 | 4 | namespace MyCountries.Web.Models 5 | { 6 | // Add profile data for application users by adding properties to the ApplicationUser class 7 | public class ApplicationUser : IdentityUser 8 | { 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /MyCountries.Web/Models/ContactModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace MyCountries.Web.Models 4 | { 5 | public class ContactModel 6 | { 7 | [Required] 8 | public string Name { get; set; } 9 | 10 | [Required] 11 | [EmailAddress] 12 | public string Email { get; set; } 13 | 14 | [Required] 15 | public string Comments { get; set; } 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /MyCountries.Web/MyCountries.Web.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 5d0ccc2b-b706-4105-92a4-20431fd418ca 9 | MyCountries.Web 10 | ..\artifacts\obj\$(MSBuildProjectName) 11 | ..\artifacts\bin\$(MSBuildProjectName)\ 12 | 13 | 14 | MyCountries.Web 15 | 16 | 17 | 2.0 18 | 22223 19 | 20 | 21 | 22 | 23 | 24 | True 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /MyCountries.Web/Properties/Assembly.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MyCountries.Web")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MyCountries.Web")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5243f607-67af-4ef2-9c71-4b8bdad6a087")] 24 | -------------------------------------------------------------------------------- /MyCountries.Web/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "IIS Express": { 4 | "commandName": "IISExpress", 5 | "launchBrowser": true, 6 | "environmentVariables": { 7 | "ASPNET_ENV": "Development" 8 | }, 9 | "sdkVersion": "dnx-clr-win-x64.1.0.0-beta8" 10 | }, 11 | "web": { 12 | "commandName": "web", 13 | "environmentVariables": { 14 | "ASPNET_ENV": "Development" 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /MyCountries.Web/Services/IEmailSender.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace MyCountries.Web.Services 4 | { 5 | public interface IEmailSender 6 | { 7 | Task SendEmailAsync(string email, string subject, string message); 8 | } 9 | } -------------------------------------------------------------------------------- /MyCountries.Web/Services/ISmsSender.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace MyCountries.Web.Services 7 | { 8 | public interface ISmsSender 9 | { 10 | Task SendSmsAsync(string number, string message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /MyCountries.Web/Services/MessageServices.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace MyCountries.Web.Services 7 | { 8 | // This class is used by the application to send Email and SMS 9 | // when you turn on two-factor authentication in ASP.NET Identity. 10 | // For more details see this link http://go.microsoft.com/fwlink/?LinkID=532713 11 | public class AuthMessageSender : IEmailSender, ISmsSender 12 | { 13 | public Task SendEmailAsync(string email, string subject, string message) 14 | { 15 | // Plug in your email service here to send an email. 16 | return Task.FromResult(0); 17 | } 18 | 19 | public Task SendSmsAsync(string number, string message) 20 | { 21 | // Plug in your SMS service here to send a text message. 22 | return Task.FromResult(0); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MyCountries.Web/ViewModels/Account/ExternalLoginConfirmationViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyCountries.Web.ViewModels.Account 8 | { 9 | public class ExternalLoginConfirmationViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | public string Email { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MyCountries.Web/ViewModels/Account/ForgotPasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyCountries.Web.ViewModels.Account 8 | { 9 | public class ForgotPasswordViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | public string Email { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MyCountries.Web/ViewModels/Account/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyCountries.Web.ViewModels.Account 8 | { 9 | public class LoginViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | public string Email { get; set; } 14 | 15 | [Required] 16 | [DataType(DataType.Password)] 17 | public string Password { get; set; } 18 | 19 | [Display(Name = "Remember me?")] 20 | public bool RememberMe { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /MyCountries.Web/ViewModels/Account/RegisterViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyCountries.Web.ViewModels.Account 8 | { 9 | public class RegisterViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | [Display(Name = "Email")] 14 | public string Email { get; set; } 15 | 16 | [Required] 17 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 18 | [DataType(DataType.Password)] 19 | [Display(Name = "Password")] 20 | public string Password { get; set; } 21 | 22 | [DataType(DataType.Password)] 23 | [Display(Name = "Confirm password")] 24 | [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] 25 | public string ConfirmPassword { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /MyCountries.Web/ViewModels/Account/ResetPasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyCountries.Web.ViewModels.Account 8 | { 9 | public class ResetPasswordViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | public string Email { get; set; } 14 | 15 | [Required] 16 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 17 | [DataType(DataType.Password)] 18 | public string Password { get; set; } 19 | 20 | [DataType(DataType.Password)] 21 | [Display(Name = "Confirm password")] 22 | [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] 23 | public string ConfirmPassword { get; set; } 24 | 25 | public string Code { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /MyCountries.Web/ViewModels/Account/SendCodeViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNet.Mvc.Rendering; 6 | 7 | namespace MyCountries.Web.ViewModels.Account 8 | { 9 | public class SendCodeViewModel 10 | { 11 | public string SelectedProvider { get; set; } 12 | 13 | public ICollection Providers { get; set; } 14 | 15 | public string ReturnUrl { get; set; } 16 | 17 | public bool RememberMe { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /MyCountries.Web/ViewModels/Account/VerifyCodeViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyCountries.Web.ViewModels.Account 8 | { 9 | public class VerifyCodeViewModel 10 | { 11 | [Required] 12 | public string Provider { get; set; } 13 | 14 | [Required] 15 | public string Code { get; set; } 16 | 17 | public string ReturnUrl { get; set; } 18 | 19 | [Display(Name = "Remember this browser?")] 20 | public bool RememberBrowser { get; set; } 21 | 22 | [Display(Name = "Remember me?")] 23 | public bool RememberMe { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MyCountries.Web/ViewModels/Manage/AddPhoneNumberViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyCountries.Web.ViewModels.Manage 8 | { 9 | public class AddPhoneNumberViewModel 10 | { 11 | [Required] 12 | [Phone] 13 | [Display(Name = "Phone number")] 14 | public string PhoneNumber { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /MyCountries.Web/ViewModels/Manage/ChangePasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyCountries.Web.ViewModels.Manage 8 | { 9 | public class ChangePasswordViewModel 10 | { 11 | [Required] 12 | [DataType(DataType.Password)] 13 | [Display(Name = "Current password")] 14 | public string OldPassword { get; set; } 15 | 16 | [Required] 17 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 18 | [DataType(DataType.Password)] 19 | [Display(Name = "New password")] 20 | public string NewPassword { get; set; } 21 | 22 | [DataType(DataType.Password)] 23 | [Display(Name = "Confirm new password")] 24 | [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] 25 | public string ConfirmPassword { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /MyCountries.Web/ViewModels/Manage/ConfigureTwoFactorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNet.Mvc.Rendering; 6 | 7 | namespace MyCountries.Web.ViewModels.Manage 8 | { 9 | public class ConfigureTwoFactorViewModel 10 | { 11 | public string SelectedProvider { get; set; } 12 | 13 | public ICollection Providers { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MyCountries.Web/ViewModels/Manage/FactorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace MyCountries.Web.ViewModels.Manage 7 | { 8 | public class FactorViewModel 9 | { 10 | public string Purpose { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /MyCountries.Web/ViewModels/Manage/IndexViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNet.Identity; 6 | 7 | namespace MyCountries.Web.ViewModels.Manage 8 | { 9 | public class IndexViewModel 10 | { 11 | public bool HasPassword { get; set; } 12 | 13 | public IList Logins { get; set; } 14 | 15 | public string PhoneNumber { get; set; } 16 | 17 | public bool TwoFactor { get; set; } 18 | 19 | public bool BrowserRemembered { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MyCountries.Web/ViewModels/Manage/ManageLoginsViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNet.Http.Authentication; 6 | using Microsoft.AspNet.Identity; 7 | 8 | namespace MyCountries.Web.ViewModels.Manage 9 | { 10 | public class ManageLoginsViewModel 11 | { 12 | public IList CurrentLogins { get; set; } 13 | 14 | public IList OtherLogins { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /MyCountries.Web/ViewModels/Manage/SetPasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyCountries.Web.ViewModels.Manage 8 | { 9 | public class SetPasswordViewModel 10 | { 11 | [Required] 12 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 13 | [DataType(DataType.Password)] 14 | [Display(Name = "New password")] 15 | public string NewPassword { get; set; } 16 | 17 | [DataType(DataType.Password)] 18 | [Display(Name = "Confirm new password")] 19 | [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] 20 | public string ConfirmPassword { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /MyCountries.Web/ViewModels/Manage/VerifyPhoneNumberViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyCountries.Web.ViewModels.Manage 8 | { 9 | public class VerifyPhoneNumberViewModel 10 | { 11 | [Required] 12 | public string Code { get; set; } 13 | 14 | [Required] 15 | [Phone] 16 | [Display(Name = "Phone number")] 17 | public string PhoneNumber { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Account/ConfirmEmail.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Confirm Email"; 3 | } 4 | 5 |

@ViewData["Title"].

6 |
7 |

8 | Thank you for confirming your email. Please Click here to Log in. 9 |

10 |
11 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Account/ExternalLoginConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @model ExternalLoginConfirmationViewModel 2 | @{ 3 | ViewData["Title"] = "Register"; 4 | } 5 | 6 |

@ViewData["Title"].

7 |

Associate your @ViewData["LoginProvider"] account.

8 | 9 |
10 |

Association Form

11 |
12 |
13 | 14 |

15 | You've successfully authenticated with @ViewData["LoginProvider"]. 16 | Please enter a user name for this site below and click the Register button to finish 17 | logging in. 18 |

19 |
20 | 21 |
22 | 23 | 24 |
25 |
26 |
27 |
28 | 29 |
30 |
31 |
32 | 33 | @section Scripts { 34 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 35 | } 36 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Account/ExternalLoginFailure.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Login Failure"; 3 | } 4 | 5 |
6 |

@ViewData["Title"].

7 |

Unsuccessful login with service.

8 |
9 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Account/ForgotPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model ForgotPasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Forgot your password?"; 4 | } 5 | 6 |

@ViewData["Title"].

7 |

8 | For more information on how to enable reset password please see this article. 9 |

10 | 11 | @*
12 |

Enter your email.

13 |
14 |
15 |
16 | 17 |
18 | 19 | 20 |
21 |
22 |
23 |
24 | 25 |
26 |
27 |
*@ 28 | 29 | @section Scripts { 30 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 31 | } 32 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Account/ForgotPasswordConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Forgot Password Confirmation"; 3 | } 4 | 5 |

@ViewData["Title"].

6 |

7 | Please check your email to reset your password. 8 |

9 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Account/Lockout.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Locked out"; 3 | } 4 | 5 |
6 |

Locked out.

7 |

This account has been locked out, please try again later.

8 |
9 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Account/Register.cshtml: -------------------------------------------------------------------------------- 1 | @model RegisterViewModel 2 | @{ 3 | ViewData["Title"] = "Register"; 4 | } 5 | 6 |

@ViewData["Title"].

7 | 8 |
9 |

Create a new account.

10 |
11 |
12 |
13 | 14 |
15 | 16 | 17 |
18 |
19 |
20 | 21 |
22 | 23 | 24 |
25 |
26 |
27 | 28 |
29 | 30 | 31 |
32 |
33 |
34 |
35 | 36 |
37 |
38 |
39 | 40 | @section Scripts { 41 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 42 | } 43 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Account/ResetPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model ResetPasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Reset password"; 4 | } 5 | 6 |

@ViewData["Title"].

7 | 8 |
9 |

Reset your password.

10 |
11 |
12 | 13 |
14 | 15 |
16 | 17 | 18 |
19 |
20 |
21 | 22 |
23 | 24 | 25 |
26 |
27 |
28 | 29 |
30 | 31 | 32 |
33 |
34 |
35 |
36 | 37 |
38 |
39 |
40 | 41 | @section Scripts { 42 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 43 | } 44 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Account/ResetPasswordConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Reset password confirmation"; 3 | } 4 | 5 |

@ViewData["Title"].

6 |

7 | Your password has been reset. Please Click here to log in. 8 |

9 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Account/SendCode.cshtml: -------------------------------------------------------------------------------- 1 | @model SendCodeViewModel 2 | @{ 3 | ViewData["Title"] = "Send Verification Code"; 4 | } 5 | 6 |

@ViewData["Title"].

7 | 8 |
9 | 10 |
11 |
12 | Select Two-Factor Authentication Provider: 13 | 14 | 15 |
16 |
17 |
18 | 19 | @section Scripts { 20 | @{await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 21 | } 22 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Account/VerifyCode.cshtml: -------------------------------------------------------------------------------- 1 | @model VerifyCodeViewModel 2 | @{ 3 | ViewData["Title"] = "Verify"; 4 | } 5 | 6 |

@ViewData["Title"].

7 | 8 |
9 |
10 | 11 | 12 |

@ViewData["Status"]

13 |
14 |
15 | 16 |
17 | 18 | 19 |
20 |
21 |
22 |
23 |
24 | 25 | 26 |
27 |
28 |
29 |
30 |
31 | 32 |
33 |
34 |
35 | 36 | @section Scripts { 37 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 38 | } 39 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "About MyCountries.io"; 3 | } 4 | 5 | @Html.Partial("_About") -------------------------------------------------------------------------------- /MyCountries.Web/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @model MyCountries.Web.Models.ContactModel 2 | @{ 3 | ViewBag.Title = "Contact"; 4 | } 5 | 6 | @section Scripts { 7 | 8 | 9 | } 10 | 11 | 12 |
13 | 14 |

@ViewBag.Title.

15 |

@ViewBag.Message

16 |
17 | 18 |
19 | 20 |
21 |
22 | @if (ViewBag.Result != null) 23 | { 24 |
@ViewBag.Result
25 | } 26 |
27 |
28 | 29 | 30 |
31 |
32 | 33 | 34 |
35 |
36 | 37 | 38 |
39 |
40 | 41 | 42 |
43 |
44 |
45 |
46 |
47 |
48 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Welcome to MyCountries.io"; 3 | } 4 | 5 | @Html.Partial("_About") -------------------------------------------------------------------------------- /MyCountries.Web/Views/Manage/AddPhoneNumber.cshtml: -------------------------------------------------------------------------------- 1 | @model AddPhoneNumberViewModel 2 | @{ 3 | ViewData["Title"] = "Add Phone Number"; 4 | } 5 | 6 |

@ViewData["Title"].

7 |
8 |

Add a phone number.

9 |
10 |
11 |
12 | 13 |
14 | 15 | 16 |
17 |
18 |
19 |
20 | 21 |
22 |
23 |
24 | 25 | @section Scripts { 26 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 27 | } 28 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Manage/ChangePassword.cshtml: -------------------------------------------------------------------------------- 1 | @model ChangePasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Change Password"; 4 | } 5 | 6 |

@ViewData["Title"].

7 | 8 |
9 |

Change Password Form

10 |
11 |
12 |
13 | 14 |
15 | 16 | 17 |
18 |
19 |
20 | 21 |
22 | 23 | 24 |
25 |
26 |
27 | 28 |
29 | 30 | 31 |
32 |
33 |
34 |
35 | 36 |
37 |
38 |
39 | 40 | @section Scripts { 41 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 42 | } 43 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Manage/ManageLogins.cshtml: -------------------------------------------------------------------------------- 1 | @model ManageLoginsViewModel 2 | @using Microsoft.AspNet.Http.Authentication 3 | @{ 4 | ViewData["Title"] = "Manage your external logins"; 5 | } 6 | 7 |

@ViewData["Title"].

8 | 9 |

@ViewData["StatusMessage"]

10 | @if (Model.CurrentLogins.Count > 0) 11 | { 12 |

Registered Logins

13 | 14 | 15 | @foreach (var account in Model.CurrentLogins) 16 | { 17 | 18 | 19 | 35 | 36 | } 37 | 38 |
@account.LoginProvider 20 | @if ((bool)ViewData["ShowRemoveButton"]) 21 | { 22 |
23 |
24 | 25 | 26 | 27 |
28 |
29 | } 30 | else 31 | { 32 | @:   33 | } 34 |
39 | } 40 | @if (Model.OtherLogins.Count > 0) 41 | { 42 |

Add another service to log in.

43 |
44 |
45 |
46 |

47 | @foreach (var provider in Model.OtherLogins) 48 | { 49 | 50 | } 51 |

52 |
53 |
54 | } 55 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Manage/RemoveLogin.cshtml: -------------------------------------------------------------------------------- 1 | @model ICollection 2 | @{ 3 | ViewData["Title"] = "Remove Login"; 4 | } 5 | 6 | @if (Model.Count > 0) 7 | { 8 |

Registered Logins

9 | 10 | 11 | @foreach (var account in Model) 12 | { 13 | 14 | 15 | 31 | 32 | } 33 | 34 |
@account.LoginProvider 16 | @if ((bool)ViewData["ShowRemoveButton"]) 17 | { 18 |
19 |
20 | 21 | 22 | 23 |
24 |
25 | } 26 | else 27 | { 28 | @:   29 | } 30 |
35 | } 36 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Manage/SetPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model SetPasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Set Password"; 4 | } 5 | 6 |

7 | You do not have a local username/password for this site. Add a local 8 | account so you can log in without an external login. 9 |

10 | 11 |
12 |

Set your password

13 |
14 |
15 |
16 | 17 |
18 | 19 | 20 |
21 |
22 |
23 | 24 |
25 | 26 | 27 |
28 |
29 |
30 |
31 | 32 |
33 |
34 |
35 | 36 | @section Scripts { 37 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 38 | } 39 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Manage/VerifyPhoneNumber.cshtml: -------------------------------------------------------------------------------- 1 | @model VerifyPhoneNumberViewModel 2 | @{ 3 | ViewData["Title"] = "Verify Phone Number"; 4 | } 5 | 6 |

@ViewData["Title"].

7 | 8 |
9 | 10 |

Add a phone number.

11 |
@ViewData["Status"]
12 |
13 |
14 |
15 | 16 |
17 | 18 | 19 |
20 |
21 |
22 |
23 | 24 |
25 |
26 |
27 | 28 | @section Scripts { 29 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 30 | } 31 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/My/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Your Visits"; 3 | } 4 | 5 | @section scripts { 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | } 15 | 16 |
17 |
18 |
19 |
20 |
21 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Error"; 3 | } 4 | 5 |

Error @ViewBag.ErrorCode

6 |

An error occurred while processing your request.

-------------------------------------------------------------------------------- /MyCountries.Web/Views/Shared/_LoginPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using System.Security.Principal 2 | 3 | @if (User.Identity.IsAuthenticated) 4 | { 5 | using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" })) 6 | { 7 | @Html.AntiForgeryToken() 8 | 17 | } 18 | } 19 | else 20 | { 21 | 25 | } 26 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Shared/_Nav.cshtml: -------------------------------------------------------------------------------- 1 | 
  • 2 | 3 | 4 | 5 | 6 | Home 7 | 8 |
  • 9 |
  • 10 | 11 | 12 | 13 | 14 | Contact 15 | 16 |
  • 17 |
  • 18 | 19 | 20 | 21 | 22 | About 23 | 24 |
  • 25 | 26 | 27 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Shared/_about.cshtml: -------------------------------------------------------------------------------- 1 | 
    2 |
    3 |
    4 |

    @ViewBag.Title

    5 |

    @ViewBag.Message

    6 |

    7 | This site is an experiment. This project has been build to learn how ASP.NET 5 will change the way 8 | building web projects on the Microsoft stack will work. In addition, this site does provide some real 9 | functionality. With it, you can add and share a set of country visits and share them with your friends. 10 |

    11 |

    12 | The expectation is that this site will be updated as ASP.NET 5 moves towards official release. Not all 13 | the features of the site are available or complete yet, but you should be able to join, add, and share your 14 | country visits right now. 15 | The code for this site is open source and is available on GitHub. Feel free 16 | to add comments, issues, or pull requests there. 17 |

    18 |
    19 |

    To get started, register with the website and start adding your visits: Get Started

    20 |
    21 |
    22 |
    -------------------------------------------------------------------------------- /MyCountries.Web/Views/Templates/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @using MyCountries.Web; 2 | @{ 3 | Layout = ""; 4 | } 5 | -------------------------------------------------------------------------------- /MyCountries.Web/Views/Templates/editVisit.cshtml: -------------------------------------------------------------------------------- 1 | @model MyCountries.Web.Data.Visit 2 | 3 |
    4 |

    Edit Visit

    5 |
    One Moment Please....
    6 |
    7 |
    8 | 9 | 10 | * 11 | Minimum length three characters 12 |
    13 | 14 |
    15 | 16 | @Html.DropDownList("country", (IEnumerable)ViewBag.Countries, new { @class = "form-control", ng_model = "vm.theVisit.country", required = true }) 17 | * 18 |
    19 | 20 |
    21 | 22 | 23 | * 24 | Must be MM/DD/YYYY. 25 |
    26 | 27 |
    28 | 29 | 30 |
    31 | 32 |
    33 | 34 | 35 |
    36 | 37 |
    38 | 39 | 40 |
    41 | 42 |
    43 | 44 |