Value cannot be null or empty. Parameter name linkText - c#

I have a project that similar on site in "asp.net MVC for professional" book,
so i have a problem with navigation bar, problem in view.
the text of error is:
Value cannot be null or empty.
Имя параметра: linkText
#foreach (var link in Model)
{
#Html.RouteLink(link, new
{
controller = "Profile"
,
I understand that problem in link, but I have no idea how to fix it.
below code of controllers and view.
Menu.cshtml
#model IEnumerable<string>
#Html.ActionLink("List", "Profile")
#foreach (var link in Model)
{
#Html.RouteLink(link, new
{
controller = "Profile",
action = "List",
category = link,
page = 1
})
}
NavController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using HoboAnimal.Domain.Abstract;
namespace HoboAnimal.WebUI.Controllers
{
public class NavController : Controller
{
private IProfileRepository repository;
public NavController(IProfileRepository repo)
{
repository= repo;
}
public PartialViewResult Menu(){
IEnumerable<string> categories = repository.Profiles.
Select(x => x.Category).
Distinct().
OrderBy(x => x);
return PartialView(categories);
}
}
}
Layout
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>#ViewBag.Title</title>
<link href="~/Content/Site.css" type="text/css" rel="stylesheet" />
</head>
<body>
<div id="header">
</div>
<div id="categories">
#{Html.Action("Menu","Nav");}
</div>
<div id="content">
#RenderBody()
</div>
</body>
</html>
Thank you

Since linkText is first argument of ActionLink and RouteLink, this mean that 1 or more of yours "link" in Model is empty string. Check it before create link:
#foreach (var link in Model)
{
if(!String.IsNullOrEmpty(link.toString())
{
#Html.RouteLink(link, new
{
controller = "Profile",
action = "List",
category = link,
page = 1
})
}
}
or remove empty rows from selection:
IEnumerable<string> categories = repository.Profiles.
Select(x => x.Category).
Distinct().
Where(x => !String.IsNullOrEmpty(x)).
OrderBy(x => x);

This error:
Value cannot be null or empty. Имя параметра: linkText
only says that the linkText parameter is needed (he can't be null or empty) in the ActionLink method.
for example you could write like this:
#Html.ActionLink(" ","List", "Profile")
it should help.

Related

Reusing the same html code as a partial view 'n' number of times in the same index.cshtml page

I have a partial view which renders a visual form made entirely in HTML with some .css. What I want to do is reuse this same form in the same page [n] number of times. In my HomeController class I am instantiating the model as such:
public IActionResult Index()
{
List<Foo> foos = new List<Foo>();
foos.Add(new Foo { Name = "John" });
foos.Add(new Foo { Name = "Dave" });
foos.Add(new Foo { Name = "Sean" });
foos.Add(new Foo { Name = "Alan" });
return View(foos);
}
Then in my index.cshtml I am iterating using the list I receive from my controller and generating a partial view based on the length of my list
#model List<HelloWorld.Models.Foo>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Foo</title>
<link rel="stylesheet" href="~/foo/styles.css" />
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="~/foo/FooActions.js"></script>
</head>
<body>
#{
foreach (Foo foo in Model)
{
ViewData["Name"] = foo.Name;
<partial name="_Foo" view-data="ViewData" />
}
}
</body>
</html>
This is how I have my partial view set up:
<script type="text/javascript">
init('#ViewBag.Name');
</script>
<div class="foo-background">
<section>
<div>
<span class="score-text" id="redText">0</span>
</div>
<div class="green-bar"></div>
<div class="red-bar"></div>
<div>
<span class="bonus-score-text" id="greenText">0</span>
</div>
</section>
<section>
<div class="alphanumeric-display">
<p class="alphanumeric-display-text" id="textLine1">Text</p>
<p class="alphanumeric-display-text" id="textLine2">Text</p>
<p class="alphanumeric-display-text" id="textLine3">Text</p>
</div>
<div>
<span class="person-grade-text" id="goldText">0</span>
</div>
</section>
</div>
This form pulls data from a local database and displays data based on the person its tied to. The data shows up fine if its only displaying data of one person in the page. I'm using JavaScript to grab either the class or the id of these html elements and update their respective data.
But now what its doing is showing all the forms side-by-side, only, the data is wrong. None of the forms show the data from the table as they appear in the database. Upon closer inspection looks like it has a problem where each of these forms cant have the same class or ids. I'm getting this in error in all places where I have class or id elements
id attribute value must be unique: Document has multiple static
elements with the same id attribute: textLine1
Its the same error for each of my html elements.
Can someone help me understand what I am doing wrong? What can I do in order to get this to work properly?

TempData still available after subsequent http requests?

My textbook says that "TempData gets destroyed immediately after it’s used in subsequent HTTP request", so I write a simple test to verify
below is my code:
// SimpleForm.cshtml is just a simple view that uses a form to send post request to ReceiveForm action method
//Result.cshtml is just a simple view that products an output
public class HomeController : Controller
{
public ViewResult Index() => View("SimpleForm");
[HttpPost]
public RedirectToActionResult ReceiveForm(string name, string city)
{
TempData["name"] = name;
TempData["city"] = city;
return RedirectToAction(nameof(Transfer));
}
public RedirectToActionResult Transfer()
{
string name = TempData["name"] as string;
string city = TempData["city"] as string;
return RedirectToAction(nameof(Data));
}
public ViewResult Data()
{
string name = TempData["name"] as string;
string city = TempData["city"] as string;
return View("Result", $"{name} lives in {city}");
}
}
so when the application runs, it goes to Index() action method first, I fill up the form with name and city and press submit button, then it goes to ReceiveForm() action method, which setup TempData and redirect to Transfer() action method.
In the Transfer() action method, I read TempData, so TempData should get destroyed and unavailable to read in the next http request according to the textbook.
But in the Data(), I find that I can still read TempData, see the screenshot below:
and I checked the chrome dev tool, there was one post request and two get requests, which is all good and correct. so when does TempData actually get destroyed ?
additional code:
SimpleForm.cshtml:
#{ Layout = null; }
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Controllers and Actions</title>
<link rel="stylesheet" asp-href-include="lib/bootstrap/dist/css/*.min.css" />
</head>
<body class="m-1 p-1">
<form method="post" asp-action="ReceiveForm">
<div class="form-group">
<label for="name">Name:</label>
<input class="form-control" name="name" />
</div>
<div class="form-group">
<label for="name">City:</label>
<input class="form-control" name="city" />
</div>
<button class="btn btn-primary center-block" type="submit">Submit</button>
</form>
</body>
</html>
Result.cshtml:
#model string
#{ Layout = null; }
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Controllers and Actions</title>
<link rel="stylesheet" asp-href-include="lib/bootstrap/dist/css/*.min.css" />
</head>
<body class="m-1 p-1">
Model Data: #Model
</body>
</html>
For your scenario, this is caused by RedirectToActionResult. For RedirectToActionResult, which is IKeepTempDataResult.
public class RedirectToActionResult : ActionResult, IKeepTempDataResult
SaveTempDataFilter is filter that saves temp data. It will call SaveTempData.
private static void SaveTempData(
IActionResult result,
ITempDataDictionaryFactory factory,
IList<IFilterMetadata> filters,
HttpContext httpContext)
{
var tempData = factory.GetTempData(httpContext);
for (var i = 0; i < filters.Count; i++)
{
if (filters[i] is ISaveTempDataCallback callback)
{
callback.OnTempDataSaving(tempData);
}
}
if (result is IKeepTempDataResult)
{
tempData.Keep();
}
tempData.Save();
}
For SaveTempData, it will check whether IActionResult result is IKeepTempDataResult. If it is, it will keep the tempData.
If you want to avoid keep tempData between request, you could change RedirectToAction to LocalRedirect like
public IActionResult Transfer()
{
string name = TempData["name"] as string;
string city = TempData["city"] as string;
return LocalRedirect("~/Home/Data");
//return RedirectToAction(nameof(Data));
}

Cant find page after POST redirect C#

I go to a View, submit data via POST, but the redirect cannot find the Controller method. What am I doing wrong here? After submitting the form I get:
404 error: cannot find page. URL is: http://localhost:52008/InternalController/UpdateCardFormPost
Snippet from InternalController.cs:
public ActionResult UpdateCardFormView()
{
var CardToUpdate = new CardView();
return View(CardToUpdate);//return implementation of Cards.cshtml with the empty model that was passed to it
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UpdateCardFormPost(CardView c)
{
CardModelIO.WriteCard(c);//#TODO: IMPLEMENT
return View("CardDetailView", c);
}
UpdateCardFormView.cshtml (the view with the form I am submitting):
#using LeanKit.API.Client.Library.TransferObjects
#model CardView
<!DOCTYPE html>
<html>
<!--Form used to change a card
STARTING DISPLAY called by in Internal/UpdateCardFormView
ENDING DISPLAY (post) called by UpdateCardForm in InternalController a specified below-->
<head>
</head>
<body>
#Html.BeginForm("UpdateCardFormPost", "InternalController", FormMethod.Post)
#Html.TextBoxFor(c => c.AssignedUserName);
<input type="submit" value="Submit Changes" />
</body>
</html>
Heres the CardDetailView.cshtml (the view I should be redirected to):
#using LeanKit.API.Client.Library.TransferObjects
#model IEnumerable<CardView>
<!--used for displaying an individual card in detail view
referenced in UpdateCardFormPost() method of Internal controller-->
<!DOCTYPE html>
<html>
<head>
</head>
<body>
CardView j = Model;
<p>j.AssignedUserId</p>
</body>
</html>
You've specified the controller name as InternalController but it's probably just called "Internal".
Try changing
#Html.BeginForm("UpdateCardFormPost", "InternalController", FormMethod.Post)
to
#Html.BeginForm("UpdateCardFormPost", "Internal", FormMethod.Post)
you are missing closing form tag
you should do it like
using (#Html.BeginForm("UpdateCardFormPost", "InternalController", FormMethod.Post))
{
...
}
#using(Html.BeginForm())
{
#Html.TextBoxFor(c => c.AssignedUserName);
<input type="submit" value="Submit Changes" />
}

Razor: Transfer input text + Model to a controller

Hy everybody,
In my Razor View page, I have a text input. I want to call a controller by using the "onchange" event and add my input value to a list contained in my Razor Model.
This is my html page:
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>MyForms</title>
</head>
<body>
<label>Code</label>
<form method="post" action="">
<input name="NPItem" maxlength="11" autofocus onkeypress="return isNumberKey(event)" onchange="location.href = '#Url.Action("addtoList", "MyController", new { formsData = Newtonsoft.Json.JsonConvert.SerializeObject(Model) })';"/>
</form>
<table border="1" id="listeNPAI">
<tr>
<th>Index</th>
<th>Value</th>
</tr>
#{
foreach (Tuple<string, string> item in Model.list) {
<tr>
<td>#item.Item1</td>
<td>#item.Item2</td>
</tr>
}
}
</table>
</body>
</html>
This is my called controller action :
public ActionResult addtoList(string formsData) {
formsData _form = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelClass>(formsData);
string input = Request["NPItem"];
if (input == null) { input = ""; } else { input = input.Trim(); }
if (input.Length == 11) {
_form.list.Add(new Tuple<string, string>(input.Substring(0, 5), input.Substring(6)));
}
return View("FormulaireNPAI", _form);
}
I add the input text value to the list in my controller action. The problem is that input is always '==null' (because there is no submit). However, it works when I press the Enter keyboard button.
Help, please
Thks in advance
You could do something like this:
$("#element").on("click", function() {
$.ajax({
url: "action",
type: "GET",
data: { data }
})
.done(function(partialViewResult) {
$("#yourViewWrapper").html(partialViewResult);
});
});
i.e. made AJAX call when you need and then refresh your view.

How can I prevent my list item to disappear after page reload Mvc asp.net c#

I am really new to MVC and C#
I modified the _Layout.cshtml to have a menu and on click of any menu item I have a jquery function to create sub menu items based on the parent that I clicked. When I click on any link in the sub menu It reloads the master page and clears my sub menu which is something I don't like. Can someone help me recreate dynamically the same sub menu after page reload or any idea to fix that issue is welcome
OK
I created a controller that I am accessing in my _Layout to create my menu bar
public abstract class MainController : Controller
{
private static HRMenuDataContext db = new HRMenuDataContext();
public static string theVal, toCheck;
public static int num;
public static HRMenuDataContext theData
{
get { return db; }
}
public MainController()
{
//ViewData["Parent"] = from c in theData.psHCMLanguages
// where
// (from m in theData.psHCMMenus
// where
// m.sModule == "AP"
// select m.sMainRef
// ).Distinct().Contains(c.szCode)
// select c;
ViewData["parent"] = theData.theParent("HR");
ViewData["check"] = theData.doCheck(toCheck);
ViewData["Child"] = from c in theData.psHCMLanguages
where
(from m in theData.psHCMMenu_1s
let parent = theVal
where
m.sModule == "HR" &&
m.sSubRef == parent
select
m.sPrompt
).Contains(c.szCode)
select c;
}
}
in my _Layout.cshtml I have this
#using Menus.Data;
#using Menus.Controllers;
#using System.Linq;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title - Persol Systems</title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
<link href="~/Content/theStyle.css" rel="stylesheet" />
<style type="text/css">
#theSide {
clear:both;
position:relative;
float:left;
left:100px;
bottom:50px;
top:0;
border:1px solid red;
width:150px;
height:600px;
}
</style>
</head>
<body>
#{
string[] name;
char[] sep = { ' ', '/', '\\', '.' };
string mess="";
}
<header>
<div class="content-wrapper">
<div class="float-left">
<p class="site-title">#Html.ActionLink("your logo here", "Index", "Home")</p>
</div>
<div class="float-right">
<section id="login">
#Html.Partial("_LoginPartial")
</section>
<nav>
<ul id="menux">
#{
foreach (var c in (IEnumerable<theParentResult>)ViewData["parent"])
{
<li><a>#c.English </a>
#{MainController.theVal = c.szCode;}
<ul class="firstChild">
#{foreach (var d in (IEnumerable<psHCMLanguage>)ViewData["Child"])
{
var data = MainController.theData.doCheck(d.szCode);
if ((int)data == 1)
{
<li><a onclick="theAlert('#d.szCode','#d.English')">#d.English</a>
#{
MainController.theVal = d.szCode;
}
</li>
}
else if (data == 0)
{
name = d.English.Split(sep);
foreach (string nams in name)
{
mess += nams;
}
<li>
<a onclick="theAlert('#d.szCode','#d.English')">#d.English</a>
#*#Html.ActionLink(d.English, mess, c.English)*#
</li>
mess = "";
Array.Clear(name, 0, name.Length);
}
}
}
</ul>
</li>
}
}
</ul>
</nav>
</div>
</div>
</header>
<div id="body">
<div id="theSide">
<ul id="sidePanel">
</ul>
</div>
#RenderSection("featured", required: false)
<section class="content-wrapper main-content clear-fix">
#RenderBody()
</section>
</div>
<footer>
<div class="content-wrapper">
<div class="float-left">
<p>© #DateTime.Now.Year - Persol Systems</p>
</div>
</div>
</footer>
#Scripts.Render("~/bundles/jquery")
#RenderSection("scripts", required: false)
<script type="text/javascript">
function theAlert(theId, theName) {
$("ul#sidePanel").contents().remove();
$("ul#sidePanel ").append("<li id='" + theId + "'><a >" + theId + "</a></li>");
$("li#" + theId + "> a").click(function (e) {
window.location.href("../Home/About");
});
return false;
}
</script>
</body>
</html>
on click of the link It reloads the entire page and clears my sidePanel
HTTP is stateless which means any data that you do not persist will get lost between postbacks. If you want to persist that information you will need to use Javascript to send the menu structure to the server through Ajax or use browser based local storage.
An example scenerio
model
public class Menu
{
// prop parent for example
public List<Parents> parents{ get; set; }
// prop child
public List<Childs> child{ get; set; }
// prop check
public bool checked { get; set; }
}
controller
public class Menu: Controller
{
public ActionResult _MainMenu()
{
Menu menu = new Menu();
menu.Parent = // parent elements from your db context
menu.Child = // child elements from your db context
menu.Parent = // check element from your db context
return PartialView(menu);
}
}
_MainMenu.cshtml
#model Menu
// same like your layout view, fill here like layout
// for example
#foreach(var parent in Model.Parents)
{
// generate menus
....
}
_Layout.cshtml
...
<nav>
<ul id="menux">
#Html.Action("_MainMenu", "Menu")
</ul>
</nav>
...
I suggest you an example code you should modify Data Types that you want.

Categories

Resources