My Controller does not receive data from a Form in my View.
I've used basically the exact same code before with other models and there it works pefectly fine.
Can someone explain why this doesn't work?
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult ChangeWiFiNetwork(Models.Settings.NetworkSettings model)
{
Logger.LogInformation("SSID:", model.SSID);
Logger.LogInformation("PASS:", model.Password);
return RedirectToAction("Index");
}
View:
@model Webserver.Models.Settings.Settings
<h1>Settings</h1>
<div class="row">
<div class="col-6">
<form asp-action="ChangeWiFiNetwork">
<div class="form-group">
<label asp-for="Network.SSID" class="control-label"></label>
<input asp-for="Network.SSID" class="form-control" />
<span asp-validation-for="Network.SSID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Network.Password" class="control-label"></label>
<input asp-for="Network.Password" class="form-control" />
<span asp-validation-for="Network.Password" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
Models:
namespace Webserver.Models.Settings
{
public class Settings
{
public NetworkSettings Network { get; set; }
}
}
namespace Webserver.Models.Settings
{
public class NetworkSettings
{
public string SSID { get; set; }
public string Password { get; set; }
}
}
Output
SSID:
PASS:
Both show as null in Debug-Mode.
Firefox Network-Analysis shows Network.SSID and Network.Password are being sent in Form-Data.
I'm using .Net 5
Thanks
CodePudding user response:
For now I'll just extract the Values from Request.Form manually.
This is really awful code, but I just can't figure out why the model binding doesn't work.
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult ChangeWiFiNetwork(Models.Settings.NetworkSettings throwaway)
{
if (!(Request.Form.ContainsKey("NetworkSettings.SSID") && Request.Form.ContainsKey("NetworkSettings.Password")))
{
throw new Exception("SSID or Password missing!");
}
Models.Settings.NetworkSettings settings = new()
{
SSID = Request.Form["NetworkSettings.SSID"],
Password = Request.Form["NetworkSettings.Password"]
};
Logger.LogInformation("SSID: " settings.SSID);
Logger.LogInformation("PASS: " settings.Password);
return RedirectToAction("Index");
}
CodePudding user response:
fix the view, since you use AntiForgeryToken add it to form
<form asp-action="ChangeWiFiNetwork">
@Html.AntiForgeryToken()
and action input parameter should be the same as model
public IActionResult ChangeWiFiNetwork(Models.Settings.Settings model)
CodePudding user response:
You set the model as @model Webserver.Models.Settings.Settings
but in your action, you set the input parameter as Models.Settings.NetworkSettings model
,
So you should change your action like this:
public IActionResult ChangeWiFiNetwork(Models.Settings.Settings model)
Or changing the binding model in the view:
@model Webserver.Models.Settings.NetworkSettings
Anyway you need to keep the model the same both in view and controller action.