how to add and delete favorites in asp.net core api - asp.net-web-api

I develop a news application with ASP.net API. I want users to be able to add and deleted their favorites articles. I created a Favorites model like this:
public class Favorites{
public String userId {get; set;}
public UserEntity User {get; set;}
public int articleId {get; set; }
public virtual Article article {get; set;}
}
I initialized it with dotnet fluentapi:
modelBuilder.Entity<Favorites>().HasKey(a => new{ a.articleId, a.userId });
this is how the controller looks like :
public class FavoritesController : ControllerBase
{
private readonly DatabaseContext _context;
public FavoritesController(DatabaseContext context)
{
_context = context;
_context.Database.EnsureCreated();
}
// GET: api/Favorites
[HttpGet(Name = nameof(GetAllFavorites))]
public async Task<ActionResult<IEnumerable<FavoriteDTo>>> GetAllFavorites( [FromQuery] NewRoomQueryParameters queryParameter)
{
IQueryable<Favorites> favs = _context.Favorites;
if (!string.IsNullOrEmpty(queryParameter.sortBy))
{
if (typeof(Favorites).GetProperty(queryParameter.sortBy) != null)
{
favs = favs.OrderByCustom(queryParameter.sortBy, queryParameter.SortOrder);
}
}
if (!string.IsNullOrEmpty(queryParameter.userId))
{
favs = favs.Where(p => p.userId == queryParameter.userId);
}
return await favs.Include(a => a.Article)
.ThenInclude(a => a.Author)
.Include(a => a.Article)
.ThenInclude(a => a.Comments)
.Select(x => favoriteToDTo(x)).ToListAsync();
}
// GET: api/Favorites/5
[HttpGet("{id}")]
public async Task<ActionResult<FavoriteDTo>> GetFavorites(int id)
{
IQueryable<Favorites> favs = _context.Favorites;
var favorites = await favs.Include(x => x.Article).FirstOrDefaultAsync(x => x.articleId == id ) ;
if (favorites == null)
{
return NotFound();
}
return favoriteToDTo(favorites);
}
// POST: api/Favorites
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPost]
public async Task<ActionResult<FavoriteDTo>> PostFavorites(FavoriteDTo favDTo)
{
var fav = new Favorites
{
articleId = favDTo.articleId,
userId = favDTo.userId
};
_context.Favorites.Add(fav);
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateException)
{
if (FavoritesExists(fav.articleId))
{
return Conflict();
}
else
{
throw;
}
}
return CreatedAtAction(nameof(GetFavorites), new { id = fav.articleId }, fav);
}
// DELETE: api/Favorites/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteFavorites(int id)
{
var favorites = await _context.Favorites.FindAsync(id);
if (favorites == null)
{
return NotFound();
}
_context.Favorites.Remove(favorites);
await _context.SaveChangesAsync();
return NoContent();
}
private static FavoriteDTo favoriteToDTo(Favorites favorites) => new FavoriteDTo
{
articleId = favorites.articleId,
Article = favorites.Article,
User = favorites.User,
userId = favorites.userId
};
private bool FavoritesExists(int id)
{
return _context.Favorites.Any(e => e.articleId == id);
}
}
I can add Favorites just fine. But I cannot remove them. Can somebody help me out ? if it is not the good
way to implement this functionality , please I would like to learn how to do it the right way.

It depends on How you want to delete the favorite. If you want to delete the Article from Favorite for a user,
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteFavoritesForUser(int Articleid, string userId)
{
var favorites = await _context.Favorites.FindBy(x=>x.UserId ==userId && x=>x.ArticleId ==Articleid);
if (favorites == null)
{
return NotFound();
}
_context.Favorites.RemoveRange(favorites);
await _context.SaveChangesAsync();
return NoContent();
}

Replace
_context.Favorites.Remove(favorites);
with
_context.Favorites.RemoveRange(favorites);

Related

Image not displaying in view for ASP.NET Core MVC app but dev tools shows it is there

I am still fairly new to ASP.NET Core and I am not 100% sure on what I am doing, but I have hobbled together a recipe keeper program, but I am having issues displaying the images.
When I run the program, the view shows that it is getting the image file name and the dev tools shows the correct src code, but the image is still not showing up. I have the code set to show a generic "no image" image when the view can't find the image assigned to the particular recipe but that shouldn't be the case.
I originally had this part working and I'm not sure why it is not anymore. I have tried to retrace my steps from when I noticed the issue, but it has been several days since I completed the image part of this program, so I am not sure where the issue is.
View showing image is there
Page showing generic image
DevTools showing the src
RecipeController:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using WhatsForDinner.Data;
using WhatsForDinner.Models;
namespace WhatsForDinner.Controllers
{
public class RecipesController : Controller
{
private readonly ApplicationDbContext _context;
private readonly IWebHostEnvironment webHostEnvironment;
public RecipesController(ApplicationDbContext context, IWebHostEnvironment webHostEnvironment)
{
_context = context;
this.webHostEnvironment = webHostEnvironment;
}
// GET: Recipes
public async Task<IActionResult> Index()
{
var applicationDbContext = _context.Recipes
.Include(r => r.ApplicationUser)
.Where(a => a.ApplicationUser.Id == HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value);
return View(await applicationDbContext.ToListAsync());
}
// GET: Recipes/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null || _context.Recipes == null)
{
return NotFound();
}
var recipe = await _context.Recipes
.Include(r => r.ApplicationUser)
.FirstOrDefaultAsync(m => m.RecipeId == id);
if (recipe == null)
{
return NotFound();
}
return View(recipe);
}
// GET: Recipes/Create
public IActionResult Create()
{
//ViewData["ApplicationUserId"] = new SelectList(_context.User, "Id", "Id");
//ViewBag.ApplicationUserId = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
return View();
}
// POST: Recipes/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("RecipeId, UploadDateAndTime, RecipeTitle, RecipeDescription, PrepTime, NumOfServings, ServingSize, Ingredients, Directions, Notes, RecipePhoto, ApplicationUserId, RecipePhoto")] Recipe recipe, IFormFile file)
{
if (ModelState.IsValid)
{
string uniqueFileName = null;
if (file != null)
{
string uploadsFolder = Path.Combine(webHostEnvironment.WebRootPath, "Images");
uniqueFileName = file.FileName;
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
file.CopyTo(fileStream);
}
}
recipe.RecipePhoto = uniqueFileName;
recipe.ApplicationUserId = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
_context.Add(recipe);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
// ViewData["ApplicationUserId"] = new SelectList(_context.User, "Id", "Id", recipe.ApplicationUserId);
// ViewBag.ApplicationUserId = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
return View(recipe);
}
// GET: Recipes/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null || _context.Recipes == null)
{
return NotFound();
}
var recipe = await _context.Recipes.FindAsync(id);
if (recipe == null)
{
return NotFound();
}
// ViewData["ApplicationUserId"] = new SelectList(_context.User, "Id", "Id", recipe.ApplicationUserId);
// ViewBag.ApplicationUserId = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
return View(recipe);
}
// POST: Recipes/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("RecipeId, UploadDateAndTime, RecipeTitle, RecipeDescription, PrepTime, NumOfServings, ServingSize, Ingredients, Directions, Notes, ApplicationUserId")] Recipe recipe)
{
if (id != recipe.RecipeId)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
recipe.ApplicationUserId = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
_context.Update(recipe);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!RecipeExists(recipe.RecipeId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
// ViewData["ApplicationUserId"] = new SelectList(_context.User, "Id", "Id", recipe.ApplicationUserId);
// ViewBag.ApplicationUserId = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
return View(recipe);
}
// GET: Recipes/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null || _context.Recipes == null)
{
return NotFound();
}
var recipe = await _context.Recipes
.Include(r => r.ApplicationUser)
.FirstOrDefaultAsync(m => m.RecipeId == id);
if (recipe == null)
{
return NotFound();
}
return View(recipe);
}
// POST: Recipes/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
if (_context.Recipes == null)
{
return Problem("Entity set 'ApplicationDbContext.Recipes' is null.");
}
var recipe = await _context.Recipes.FindAsync(id);
if (recipe != null)
{
_context.Recipes.Remove(recipe);
}
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool RecipeExists(int id)
{
return _context.Recipes.Any(e => e.RecipeId == id);
}
}
}
I am not sure why the images are not showing anymore. Any thoughts?
I am not sure why the images are not showing anymore. Any thoughts?
Well, your issue is pretty obvious, as you are using type="image/*" to display image. However, this is not the correct way to do that. I have reproduced your issue thus have a look the solution as well.
Solution:
You should use accept="image/*"> instead of type="image/*". This the reason your image has not displayed. Your full code should be as following:
<td>
<object class="card-img-top" height="50" width="75" data="~/Image/#Html.DisplayFor(modelItem=>item.RecipePhoto)" accept="image/*">
</object>
</td>
Another way:
<td>
<object class="card-img-top" height="50" width="75" data="~/ImageName/Cover/#item.RecipePhoto" accept="image/*">
</object>
</td>
Output:

Xamarin forms monkey chat

I am using monkey chat in my mobile application(Xamrin forms based). While sending a message on IOS, on a real device, I have to click the send button 2 times. First time when I click, it minimizes the keyboard and 2nd time, it sends the message. Please suggest.
How do I send a message on one click?
Here is my send message function
namespace Budocode.ViewModels
{
public class MainChatViewModel : BaseViewModel
{
public ObservableRangeCollection Messages { get; }
ITwilioMessenger twilioMessenger;
string outgoingText = string.Empty;
public string OutGoingText
{
get { return outgoingText; }
set { SetProperty(ref outgoingText, value); }
}
public ICommand SendCommand { get; set; }
public ICommand LocationCommand { get; set; }
public MainChatViewModel()
{
// Initialize with default values
twilioMessenger = DependencyService.Get<ITwilioMessenger>();
Messages = new ObservableRangeCollection<ChatMessage>();
SendCommand = new Command(() =>
{
var message = new ChatMessage
{
Text = OutGoingText,
IsIncoming = false,
ProfileId = "profile" + GlobalSettingsDataSource.Current.SelectedProfileImageId + ".png",
MessageDateTime = DateTime.Now,
FromUser = GlobalSettingsDataSource.Current.SelectedProfile
};
if (string.IsNullOrWhiteSpace(OutGoingText))
return;
Messages.Add(message);
twilioMessenger?.SendMessage(message.Text, message.ProfileId, GlobalSettingsDataSource.Current.SelectedProfile);
OutGoingText = string.Empty;
});
LocationCommand = new Command(async () =>
{
try
{
var local = await CrossGeolocator.Current.GetPositionAsync(TimeSpan.FromSeconds(15));
var map = $"https://maps.googleapis.com/maps/api/staticmap?center={local.Latitude.ToString(CultureInfo.InvariantCulture)},{local.Longitude.ToString(CultureInfo.InvariantCulture)}&zoom=17&size=400x400&maptype=street&markers=color:red%7Clabel:%7C{local.Latitude.ToString(CultureInfo.InvariantCulture)},{local.Longitude.ToString(CultureInfo.InvariantCulture)}&key=";
var message = new ChatMessage
{
Text = "I am here",
AttachementUrl = map,
ProfileId = "profile" + GlobalSettingsDataSource.Current.SelectedProfileImageId + ".png",
IsIncoming = false,
MessageDateTime = DateTime.Now
};
Messages.Add(message);
twilioMessenger?.SendMessage("attach:" + message.AttachementUrl, message.ProfileId, GlobalSettingsDataSource.Current.SelectedProfile);
}
catch (Exception ex)
{
}
});
if (twilioMessenger == null)
return;
twilioMessenger.MessageAdded = (message) =>
{
//if (message.ProfileId == "Icon.png")
Device.BeginInvokeOnMainThread(() =>
{
if (message.FromUser != GlobalSettingsDataSource.Current.SelectedProfile)
{
message.IsIncoming = true;
}
else
{
message.IsIncoming = false;
}
Messages.Add(message);
});
};
}
public async void InitializeMock(string channelName)
{
try
{
var id = CrossDeviceInfo.Current.Id;
var userId = PersistantData.Current.UserAccount.Properties["user_id"];
HttpResponseMessage appResponse = CommonUtility.GetApiContent(
String.Format(ClientConfiguration.TwilioServiceChatHistory, id, GlobalSettingsDataSource.Current.SelectedProfile, channelName));
if (appResponse.IsSuccessStatusCode)
{
var chatContent = await appResponse.Content.ReadAsStringAsync();
List<ChatMessage> chatMsgs = JsonConvert.DeserializeObject<List<ChatMessage>>(chatContent);
Messages.ReplaceRange(chatMsgs);
}
}
catch
{
// ignore if there are any issues with twilio
}
}
}
}

how to delete functionalitty with client confirmation in asp.net core mvc 6

i have a delete method but i don't know how to delete with client confirmation,
i have a method of delete
public async Task<IActionResult> Delete(int? id, bool? saveChangesError = false)
{
if (id == null)
{
return NotFound();
}
var student = await _context.userAccount
.AsNoTracking()
.SingleOrDefaultAsync(m => m.UserID == id);
if (student == null)
{
return NotFound();
}
if (saveChangesError.GetValueOrDefault())
{
ViewData["ErrorMessage"] =
"Delete failed. Try again, and if the problem persists " +
"see your system administrator.";
}
return View();
}
// POST: Students/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
try
{
UserAccount accToDelete = new UserAccount() { UserID = id };
_context.Entry(accToDelete).State = EntityState.Deleted;
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
return RedirectToAction("Delete", new { id = id, saveChangesError = true });
}
}
how to client confirmation on first click in asp.net core mvc 6.
any new idea or any modification

Creating a new entry in Azure mobile table

Good day
I am currently facing a weird problem with my insert command on my client side I think. I can create new entries in my other models(Tables) easily but in my person model I keep getting a bad request message each time I click create account.
Backend Model:
public class Person : EntityData
{
[StringLength(20)]
public string Name { get; set; }
[StringLength(20)]
public string Surname { get; set; }
[StringLength(150)]
public string Email { get; set; }
[StringLength(15)]
public string Mobile { get; set; }
[StringLength(15)]
public string Work { get; set; }
[StringLength(14)]
public string Password { get; set; }
[StringLength(80)]
public string Company { get; set; }
public virtual City City { get; set; }
}
Client Side Controller:
namespace azuremobile
{
public partial class PersonManager
{
static PersonManager defaultInstance = new PersonManager();
MobileServiceClient client;//Initialize Mobile SDK
IMobileServiceTable<Person> accountTable;
private PersonManager()
{
var handler = new AuthHandler();
//Create our client and pass in Authentication handler
this.client = new MobileServiceClient(
Constants.ApplicationURL, handler);
this.accountTable = client.GetTable<Person>();
}
public static PersonManager DefaultManager
{
get
{
return defaultInstance;
}
private set
{
defaultInstance = value;
}
}
public MobileServiceClient CurrentClient//Provides basic access to azure mobile services
{
get { return client; }
}
public bool IsOfflineEnabled
{
get { return accountTable is Microsoft.WindowsAzure.MobileServices.Sync.IMobileServiceSyncTable<Person>; }
}
public async Task<Person> GetTodoItemsAsync(Expression<Func<Person, bool>> linq)
//public async Task<List<Person>> GetTodoItemsAsync(bool syncItems = false)
{
try
{
// return new List<Person>(await accountTable.ReadAsync());
//List<Person> newUser = await accountTable.Where(linq).Take(1).ToListAsync();
IEnumerable<Person> items = await accountTable
.Where(c => c.Name != null)
.Take(1)
.ToListAsync();
//return newUser.First();
// return await accountTable;
// .Where(c => c.Name != null)
// .Take(1)
// .ToListAsync();
}
catch (MobileServiceInvalidOperationException msioe)
{
Debug.WriteLine(#"Invalid sync operation: {0}", msioe.Message);
}
catch (Exception e)
{
Debug.WriteLine(#"Sync error: {0}", e.Message);
}
return null;
}
public async Task SaveTaskAsync(Person item)
{
// if (item.Id != null)
// await accountTable.InsertAsync(item);
// else
await accountTable.UpdateAsync(item);
}
public async Task CreateTaskAsync(Person item)
{
try
{
await accountTable.InsertAsync(item);
}
catch (MobileServiceInvalidOperationException msioe)
{
Debug.WriteLine(#"INVALID {0}", msioe.Message);
}
catch (Exception e)
{
Debug.WriteLine(#"ERROR {0}", e.Message);
}
}
}
}
Client Side Signup Screen:
public partial class SignupScreen : ContentPage
{
PersonManager manager;
public SignupScreen()
{
InitializeComponent();
NavigationPage.SetHasNavigationBar(this, false);
manager = PersonManager.DefaultManager;
LoginClicked.Clicked += async (object sender, EventArgs e) =>
{
var main = new LoginScreen();
Application.Current.MainPage = main;
Navigation.RemovePage(this);
};
}
async Task CreatedNewUser(Person items)
{
try
{
await manager.CreateTaskAsync(items);
}
catch (MobileServiceInvalidOperationException e)
{
await DisplayAlert("Info", e.Message, "Ok");
}
}
public async void OnSignUp(object sender, EventArgs e)
{
string name = this.nameEntry.Text.Trim();
string surname = this.surnameEntry.Text.Trim();
string email = this.emailEntry.Text.Trim();
string company = this.companyEntry.Text.Trim();
string work = this.workEntry.Text.Trim();
string mobile = this.mobileEntry.Text.Trim();
string password = this.passwordEntry.Text.Trim();
if (string.IsNullOrEmpty(name))
{
await DisplayAlert("Info", "Please fill in your name.", "Ok");
this.nameEntry.PlaceholderColor = this.nameEntry.TextColor = Color.FromHex("#00FF00");
nameEntry.Focus();
signUpButton.IsEnabled = true;
return;
}
if (string.IsNullOrEmpty(surname))
{
await DisplayAlert("Info", "Please fill in your surname.", "Ok");
this.surnameEntry.PlaceholderColor = this.surnameEntry.TextColor = Color.FromHex("#00FF00");
surnameEntry.Focus();
signUpButton.IsEnabled = true;
return;
}
if (string.IsNullOrEmpty(email))
{
await DisplayAlert("Info", "Please fill in your email.", "Ok");
this.emailEntry.PlaceholderColor = this.emailEntry.TextColor = Color.FromHex("#00FF00");
emailEntry.Focus();
signUpButton.IsEnabled = true;
return;
}
if (string.IsNullOrEmpty(company))
{
await DisplayAlert("Info", "Please fill in your company name.", "Ok");
this.companyEntry.PlaceholderColor = this.companyEntry.TextColor = Color.FromHex("#00FF00");
companyEntry.Focus();
signUpButton.IsEnabled = true;
return;
}
if (string.IsNullOrEmpty(mobile))
{
await DisplayAlert("Info", "Please fill in your cellphone number.", "Ok");
this.mobileEntry.PlaceholderColor = this.mobileEntry.TextColor = Color.FromHex("#00FF00");
mobileEntry.Focus();
signUpButton.IsEnabled = true;
return;
}
if (string.IsNullOrEmpty(work))
{
await DisplayAlert("Info", "Please fill in your office number.", "Ok");
this.workEntry.PlaceholderColor = this.workEntry.TextColor = Color.FromHex("#00FF00");
workEntry.Focus();
signUpButton.IsEnabled = true;
return;
}
if (string.IsNullOrEmpty(password))
{
await DisplayAlert("Info", "Please fill in your password.", "Ok");
this.passwordEntry.PlaceholderColor = this.passwordEntry.TextColor = Color.FromHex("#00FF00");
passwordEntry.Focus();
signUpButton.IsEnabled = true;
return;
}
try
{
activityIndicator.IsRunning = true;
validationLabel.IsVisible = true;
signUpButton.IsEnabled = false;
if (!string.IsNullOrEmpty(email) && !string.IsNullOrEmpty(password))
{
var OnAdd = new Person
{
Name = name,
Surname = surname,
Email = email,
Mobile = mobile,
Work = work,
Company = company,
Password = password
};
await CreatedNewUser(OnAdd);
await Navigation.PushAsync(new LoginScreen());
}
else
{
await DisplayAlert("Warning", "Could not create user account.", "Ok");
}
}
catch (Exception)
{
await DisplayAlert("Warning", "Could not create user account, problem with internet connection or server.", "Ok");
activityIndicator.IsRunning = false;
validationLabel.IsVisible = false;
signUpButton.IsEnabled = true;
}
}
}
}

ReactiveUI WhenAnyObservable doesn't work for me

My app is a winforms application and it references ReactiveUI 6.5. I'm trying to close window when user type "Exit" in a TextBox, but for some reason nothing happens.
This is my View:
public partial class HomeView : Form, IViewFor<HomeViewModel>
{
public HomeView()
{
InitializeComponent();
ViewModel = new HomeViewModel();
this.Bind(ViewModel, x => x.EnteredText, x => x.textBox.Text);
this.ViewModel.WhenAnyObservable(x => x.ExitCmd).Subscribe(_ => this.Close());
}
object IViewFor.ViewModel
{
get { return ViewModel; }
set { ViewModel = (HomeViewModel)value; }
}
public HomeViewModel ViewModel { get; set; }
}
And this is my ViewModel:
public class HomeViewModel : ReactiveUI.ReactiveObject
{
string _text;
public string EnteredText
{
get { return _text; }
set { this.RaiseAndSetIfChanged(ref _text, value); }
}
public ReactiveCommand<object> ExitCmd { get; private set; }
public HomeViewModel()
{
ExitCmd = ReactiveCommand.Create(this.WhenAny(x => x.EnteredText, y => y.Value == "Exit"));
}
}
In your ViewModel, you should describe the relationship between your Exit Command and EntertedText
public class HomeViewModel : ReactiveUI.ReactiveObject
{
private string _text;
public string EnteredText
{
get { return _text; }
set { this.RaiseAndSetIfChanged(ref _text, value); }
}
public ReactiveCommand<object> ExitCmd { get; private set; }
public HomeViewModel()
{
ExitCmd = ReactiveCommand.Create();
this.WhenAny (x => x.EnteredText, x => x.Value == "Exit")
.Where(k => k == true)
.DistinctUntilChanged()
.InvokeCommand (ExitCmd);
}
}
Then in your view, you can simply subscribe it
public partial class HomeView : Form, IViewFor<HomeViewModel>
{
public HomeView()
{
InitializeComponent();
ViewModel = new HomeViewModel();
this.Bind(ViewModel, x => x.EnteredText, x => x.textBox.Text);
this.ViewModel.ExitCmd.Subscribe (_ => this.Close());
}
object IViewFor.ViewModel
{
get { return ViewModel; }
set { ViewModel = (HomeViewModel)value; }
}
public HomeViewModel ViewModel { get; set; }
}
You've almost got it, except nothing is telling your ExitCmd to Execute. The value you're passing to ReactiveCommand.Create is the canExecute property. You should change it to this:
ExitCmd = ReactiveCommand.Create();
this.WhenAnyValue(x => x.EnteredText)
.Where(x => x == "Exit")
.InvokeCommand(ExitCmd);
InvokeCommand actually executes the command parameter, passing each value from the observable sequence into the ExecuteAsync method as the parameter.

Resources