MVC创建Steam账户时GetUsernameFromId方法Steamid为空报错
Alright, let's break down why you're hitting this error and walk through the fixes step by step. The core issues here are missing null checks, a misconfigured HTTP GET method, and out-of-order model validation logic.
1. First: Add Guard Clauses & Error Handling to GetUsernameFromId
Your current method crashes immediately if Steamid is null because it tries to call ToString() and hit the Steam API without checking the input first. Let's harden it:
public string GetUsernameFromId(string steamId) { // Block null/empty Steam IDs upfront if (string.IsNullOrWhiteSpace(steamId)) { return null; // Or throw a clear exception if you prefer: throw new ArgumentNullException(nameof(steamId)) } try { var apiUrl = $"http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key=steamapihide&steamids={Uri.EscapeDataString(steamId)}&format=xml"; XDocument doc = XDocument.Load(apiUrl); // Use ?.Value to avoid null reference if the node doesn't exist return doc.Descendants("personaname").FirstOrDefault()?.Value; } catch (Exception ex) { // Log this error (e.g., using a logging framework) so you can debug API issues later return null; // Or return a default message like "Unknown User" } }
2. Fix Your HTTP GET Create Method
Right now, your GET method is trying to create an account directly from URL parameters—this is bad practice (GET requests shouldn't modify server state, and refreshing the page would duplicate accounts). Instead, use it to return an empty creation form:
[HttpGet] public ActionResult Create() { // Pass an empty SteamAccount model to the view for form binding return View(new SteamAccount()); }
3. Rework the HTTP POST Create Method
The main problem here is that your model requires a UserName, but you're trying to set it after checking ModelState.IsValid—so the validation fails before you ever get to populate it. We need to check the Steam ID first, fetch the username, and adjust the model state accordingly:
[HttpPost] public ActionResult Create(SteamAccount acc) { // First, validate the Steam ID is provided if (string.IsNullOrWhiteSpace(acc.SteamId)) { ModelState.AddModelError("SteamId", "Please enter your Steam ID"); } else { // Fetch the Steam username var steamUsername = GetUsernameFromId(acc.SteamId); if (string.IsNullOrWhiteSpace(steamUsername)) { ModelState.AddModelError("SteamId", "Invalid Steam ID—could not retrieve your username"); } else { // Set the username and remove the required validation error (since we filled it automatically) acc.UserName = steamUsername; ModelState.Remove("UserName"); } } // Now check if the model is valid if (ModelState.IsValid) { Balance accountbalance = bctrl.CreateonCreateAccount(); acc.accountbalance = accountbalance; // Avoid null reference if AccountSkins is empty foreach (var item in acc.AccountSkins ?? new List<Skin>()) { sctrl.CreateonCreateAccount(item); } AccountRepo.Insert(acc); AccountRepo.Save(); return RedirectToAction("Index"); } else { // Return the form with error messages return View(acc); } }
4. Update Your Create View
Make sure your view only shows fields the user needs to fill out (no UserName input, since we're auto-populating it):
@model CSGO_MVC.Models.SteamAccount @{ ViewBag.Title = "Create Steam Account"; } <h2>Create Steam Account</h2> @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-horizontal"> <hr /> @Html.ValidationSummary(true, "", new { @class = "text-danger" }) <div class="form-group"> @Html.LabelFor(model => model.SteamId, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.SteamId, new { @class = "form-control" }) @Html.ValidationMessageFor(model => model.SteamId, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Password, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Password, new { @class = "form-control" }) @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.TradeLink, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.TradeLink, new { @class = "form-control" }) @Html.ValidationMessageFor(model => model.TradeLink, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Create" class="btn btn-default" /> </div> </div> </div> } <div> @Html.ActionLink("Back to List", "Index") </div>
Bonus Optimizations
- Don't hardcode your Steam API Key: Move it to
Web.config'sappSettingssection and read it withConfigurationManager.AppSettings["SteamApiKey"]—this is safer and easier to update. - Cache Steam usernames: Use
MemoryCacheto store fetched usernames for a few hours, so you don't hit the Steam API repeatedly for the same user. - Add more error handling: Handle cases where the Steam API is down or returns unexpected XML structure.
内容的提问来源于stack exchange,提问作者Farzad Henareh

