Display SQL table with Umbraco MVC - sql

I need to deliver something today and I am really stuck.
My goal is to show data from a table in Umbraco MVC (I am new to it)
Do I need to create a controller?
Because All I did was create a Document type in Umbraco with a Template.
This is what I have in my Model:
public class RechargeModel
{
public string Name { get; set; }
public string Username { get; set; }
public string Email { get; set; }
}
This is on my template:
#using Repower.Cms.Umbraco.Models;
#using Umbraco.Core.Persistence;
#{
using (var ipDb = new Database("UmbracoCMS"))
{
RechargeModel recharge;
recharge = ipDb.Fetch<RechargeModel>(new Sql().Select("TOP 100").From("umbracoUsers"));
}
}
I am getting an error saying that he cant convert type List to RechargeModel.
This is my HTML which I want to place on my page but I don't if I need to place it also inside the template or not or where to put it:
#model IEnumerable<Repower.Cms.Umbraco.Models.RechargeModel>
<table class="table table-hover">
<thead>
<tr>
<td>User Name</td>
<td>User Login</td>
<td>User Email</td>
</tr>
</thead>
<tbody>
#{
foreach (var item in Model)
{
<tr>
<td>#item.Name</td>
<td>#item.Username</td>
<td>#item.Email</td>
</tr>
}
}
</tbody>
</table>
Could someone please help? Also what about the rest of the code?
Thanks in advance!

You can access the current database using ApplicationContext.Current.DatabaseContext.Database rather than newing up a Database object.
The issue is that .Fetch() returns an List (array) of RechargeModel, where as you are trying to assign this list to a single RechargeModel.
Either use:
var database = ApplicationContext.Current.DatabaseContext.Database;
var recharges = database.Fetch<RechargeModel>(new Sql().Select("TOP 100").From("umbracoUsers"));
Or change your variable so it accepts a List:
var database = ApplicationContext.Current.DatabaseContext.Database;
List<RechargeModel> recharges = null;
recharges = database.Fetch<RechargeModel>(new Sql().Select("TOP 100").From("umbracoUsers"));
Either way, you can then iterate over this list in your view:
#foreach (var recharge in recharges )
{
<tr>
<td>#recharge.Name</td>
<td>#recharge.Username</td>
<td>#recharge.Email</td>
</tr>
}

Related

Error redirecting to page in ASP.NET Core razor pages

I want to redirect to this page
root that I want to redirect to,
but I got this error :
InvalidOperationException: No page named 'Miner/MinerDetail' matches the supplied values.
I want to redirect to this page miner/MinerDetail with a model that it is minerPartsView
Want to redirect to this page miner/MinerDetail with a model that it
is minerPartsView
Well, as per your shared screenshot, it appeared that, you were not able to redirect to your MinerDetails page due to two main reason.
Firstly, if your Request.IsAjaxRequest() executes then your next block will not executes, you have already returned the statements.
Second, reason you are not redirecting to the MinerDetails page in correct manner. As you haven't share your MinerDetails page details design thus I am sharing how you could redirect to a new razorpage with new object.
Model:
Let's assume, we have below model which we would like to pass from our intial page to MinerDetails page.
public class MinerCustomModel
{
public string? PowerSerialNumber { get; set; }
public string? MinerSerialNumber { get; set; }
public string? WorkerName { get; set; }
}
Note: In your scenario, model would be minerPartsView model
Intial Index/ Loading Page:
public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> _logger;
public IndexModel(ILogger<IndexModel> logger)
{
_logger = logger;
}
public async Task<IActionResult> OnGet()
{
var myData = new MinerCustomModel()
{
MinerSerialNumber = "SM-001",
PowerSerialNumber = "PSN-002",
WorkerName = "Worker Name"
};
string data = System.Text.Json.JsonSerializer.Serialize(myData);
return RedirectToPage("Miner/MinerDetails", new { objectData = data });
}
}
MinerDetails Page:
public class MinerDetailsModel : PageModel
{
[BindProperty]
public MinerCustomModel? minerCustomModel { get; set; } = new MinerCustomModel();
public void OnGet(string objectData)
{
var enitity = System.Text.Json.JsonSerializer.Deserialize<MinerCustomModel>(objectData);
minerCustomModel.PowerSerialNumber = enitity.PowerSerialNumber;
minerCustomModel.MinerSerialNumber = enitity.MinerSerialNumber;
minerCustomModel.WorkerName = enitity.WorkerName;
}
}
Note: Make sure, we are defining the MinerCustomModel which should a class not pageModel with [BindProperty] which should intializing as new MinerCustomModel() to avoid null reference exception.
MinerDetailsModel Page View:
#page
#model MinerDetailsModel
<h1>Miner Details</h1>
<table class="table">
<thead>
<tr>
<th>
PowerSerialNumber
</th>
<th>
MinerSerialNumber
</th>
<th>
WorkerName
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
#Model.minerCustomModel?.PowerSerialNumber
</td>
<td>
#Model.minerCustomModel?.MinerSerialNumber
</td>
<td>
#Model.minerCustomModel?.WorkerName
</td>
</tr>
</tbody>
</table>
Note: In MinerDetails view we should refer #model MinerDetailsModel page model not the MinerCustomModel or IndexModel.
Output:

How can i do multiple routes in aspnetcore razorpages with database values

I want to create specific routes with my categories. I have a categories like "laptops, phones, cameras, sound systems etc."
I created page named CategoryDetail for show category details. I want to create route with conventions for each category.
For example;
mysite.com/laptops
mysite.com/sound-systems
I writed following code.
services.AddMvc()
.AddRazorPagesOptions(options =>
{
var categories = new[] { "laptops", "sound-systems" };
foreach (var category in categories)
{
options.Conventions.AddPageRoute("/CategoryDetail", $"/{category}");
}
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
This code creating route for each category but i don't accesing category name in the CategoryDetail page.
CategoryDetailPage.cs
public class CategoryDetailModel : PageModel
{
public void OnGet()
{
string category = ???;
}
}
I created page named CategoryDetail for show category details. I want to create route with conventions for each category. For example;
mysite.com/laptops
mysite.com/sound-systems
Try to use [BindProperty] attribute. [BindProperty] binds form values and query strings with the same name as the property. (SupportsGet = true) is required for binding on GET requests.
Not clear that the design of the page where category is sent from , the following is a working demo , you could refer to and make modification as per your need.
Index.cshtml
#page
#model RazorPages2_2Test.Pages.Peoples.IndexModel
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Person[0].Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Person[0].Age)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Person) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Age)
</td>
<td>
<a asp-page="./PersonDetails" asp-route-Name="#item.Name">PersonDetails</a>
</td>
</tr>
}
</tbody>
</table>
PersonDetailsModel
public class PersonDetailsModel : PageModel
{
[BindProperty(SupportsGet = true)]
public string Name { get; set; }
public void OnGet()
{
string name = Name;
}
}
The route obtained by the above code is /Peoples/PersonDetails?Name=Sherry,change the route template in the #page directive in the .cshtml file to get the route /Peoples/PersonDetails/Sherry like below
#page "{Name?}"
#model RazorPages2_2Test.Pages.Peoples.PersonDetailsModel

How to pass all text of input selected row into action?

i have this view in my project.
I want to get the text of input in each row that is selected.
How to pass all text of input selected row into action
<table width="100%" class="table table-striped table-bordered table-hover" id="dataTables-example">
<thead>
<tr>
<th width="45%">Select</th>
<th width="45%">User Name</th>
<th width="5%">Description</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.TypeList)
{
<tr>
<td>
<input type="checkbox" name=checklist" id="checklist"/>
</td>
<td>
#Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
<input type="text" name="Extradecription"/>
</td>
</tr>
}
</tbody>
my Actions. How can I have the corresponding values of text and checkbox for the Selected rows
public IActionResult Index()
{
return View(repository.GetUser());
}
public IActionResult Save(int[] checklist,string[] Extradecription)
{
repository.Save(checklist,Extradecription);
return View(repository.GetUser());
}
If you try to get two different arrays as you have showed in you controller-action code, there will be a trouble with text for non selected items, the array for check boxes will bind as expected but for descriptions will be different, just to be clear, check the following example:
Assuming We have a list with tree options:
100 - Foo
200 - Bar
300 - Zaz
If We set the following selection for items:
Foo, a
Zaz, c
If We take a look on the request, this is the raw request:
checklist = 100,300
Extradecription = a,null,c
So, the trouble is avoid to bind null descriptions for non selected options, this is complicated, in that case I recommend to you a clear solution:
Create a model to create entity process
Create a model for option
Add a list of option model in create entity model
Initialize the model to create a new entity
Render inputs in view using asp-for tag
Retrieve the request to create a new entity
I'll assume the name of models and properties to show how to bind a typed array in your request, change the names according to your scenario.
Create entity model:
public class CreateEntity
{
public CreateEntity()
{
Items = new List<SelectedItem>();
}
// Step 3
[BindProperty]
public List<SelectedItem> Items { get; set; }
// Another properties
}
Model for option:
public class SelectedItem
{
public bool IsSelected { get; set; }
public int Code { get; set; }
public string Name { get; set; }
public string Desc { get; set; }
}
Rendering the options list:
#for (var i = 0; i < Model.Items.Count; i++)
{
<input asp-for="#Model.Items[i].IsSelected" />#Model.Items[i].Name
<input asp-for="#Model.Items[i].Desc" />
<br/>
}
The GET and POST actions in controller:
[HttpGet]
public IActionResult CreateOption()
{
// Set the items list
var model = new CreateEntity
{
Items = new List<SelectedItem>
{
new SelectedItem{ Code = 100, Name = "Foo" },
new SelectedItem{ Code = 200, Name = "Bar" },
new SelectedItem{ Code = 300, Name = "Zaz" }
}
};
return View(model);
}
[HttpPost]
public IActionResult CreateOption(CreateEntity form)
{
// Retrieve only selected items
var query = form.Items.Where(item => item.IsSelected == true).ToList();
return View();
}
If you want to know more about check boxes in Razor pages, please check this link: Checkboxes in a Razor Pages Form
Please let me know if this answer is useful.

How to pass value to view from controller?

Am a new to MVC.And am using MVC4. Am developing simple login application. Once the login success, i will get the values from the user in two textbox. If i click submit button in that page, i entered textbox value will be displayed in another page. Am facing issue on displaying the textbox value in display page.
I would like to show the controller object value in view page(Display). i could not display the data.
Model:
public class DisplayModel
{
public string setupName { get; set; }
public string displayName { get; set; }
}
Controller:
[HttpPost]
public ActionResult Display(DisplayModel setupDetails)
{
ViewData["setupDetails"] = setupDetails;
return View(setupDetails);
}
View:
#model SampleApplicationWithLoginValidation.Models.DisplayModel
#{
ViewBag.Title = "Display";
}
<h2>Display</h2>
<table border="1" style="width:100%">
<tr>
<th>Setup Name</th>
<th>Display Name</th>
</tr>
<tr><td><%:((DisplayModel)Model).setupName%></td><td>Model.displayName</td></tr>
</table>
Can anyone please help on this?
[HttpPost]
public ActionResult Display(DisplayModel setupDetails)
{
// ViewData["setupDetails"] = setupDetails; it's not necessary, because you pass the model object to view
return View(setupDetails);
}
and
</tr>
<tr><td>#Model.setupName</td><td>#Model.displayName</td></tr>
</table>
I think you use razor.
B

How to pass custom linq query to view

I'm learning and testing how to pass custom linq results
code from controller:
public ActionResult Index()
{
const int pageSize = 5;
return View(from p in db.powners
where p.petowner.StartsWith("")
orderby p.petowner.Skip(0).Take(pageSize).ToList()
select new { p.ownerid, p.petowner, p.ostreet });
}
code from view:
#model System.Collections.Generic.IEnumerable<Mvc4test2.Models.powner>
#{
ViewBag.Title = "Index";
}
<link href="../../Content/PagedList.css" rel="stylesheet" type="text/css" />
<h2>Find owner</h2>
<p>
#using (#Html.BeginForm("index", "lookup", FormMethod.Get))
{
<b>Search</b>#Html.TextBox("search")<input type="submit" value="search" />
}
</p>
<table id="ownertable">
<tr>
<th>
#Html.DisplayNameFor(model => model.petowner)
</th>
<th>
#Html.DisplayNameFor(model => model.ostreet)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.ownerid)
</td>
<td>
#Html.DisplayFor(modelItem => item.petowner)
</td>
<td>
#Html.DisplayFor(modelItem => item.ostreet)
</td>
</tr>
}
</table>
What I have tried:
#model IEnumerable<Mvc4test2.Models.powner>
and
#model System.Collections.Generic.IEnumerable<Mvc4test2.Models.powner>
Get following error:
The model item passed into the dictionary is of type 'System.Data.Objects.ObjectQuery1[<>f__AnonymousType43[System.Int32,System.String,System.String]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[Mvc4test2.Models.powner]'.`
Any idea how to pass this query to view and have it work as expected.
Of course later I will use a variable at Skip(0). I have to learn to pass it first.
Thanks
Don't pass anonymous type. Here I suggest you have two options. If Powner class has only 3 fields (ownerid, petowner, ostreet) then select new { p.ownerid, p.petowner, p.ostreet } line in your query is redundant.
public ActionResult Index()
{
const int pageSize = 5;
var model = (from p in db.powners
where p.petowner.StartsWith("")
orderby p.petowner.Skip(0).Take(pageSize) select p).ToList();
return View(model);
}
or if your Powner class is more complicated and your view has to display only ownerid, petowner and ostreet than you should create view model class which contains of these 3 properties only. Example:
public class PownerViewModel
{
public int OwnerId {get;set;} // You should modify these
public string Petowner {get;set;} // properties types
public string OStreet {get;set;} // since I don't exactly know what they are
}
.. and modify your query:
public ActionResult Index()
{
const int pageSize = 5;
var model = from p in db.powners
where p.petowner.StartsWith("")
orderby p.petowner.Skip(0).Take(pageSize)
select new PownerViewModel()
{
OwnerId = p.ownerid,
Petowner = p.petowner,
OStreet = p.ostreet
};
return View(model);
}
.. and of course change model type in your view:
#model System.Collections.Generic.IEnumerable<PownerViewModel>
P.S. There can be some errors or typos since I coded right here.
The problem is with the return type of your query in the Index controller. You should return enumerator of P.
Please check the below link:
passing the correct type from the Controller to the View?