How to connect data to a devexpress blazor report? - devexpress

I have a .net core project which cotains a report viewer on a blazor page and I'm trying to bind it to a data source without success
<div style="width: 100%; margin: auto;">
<DxDocumentViewer ReportUrl="PatientPending" Height="800px" Width="100%" #ref="Report">
<DxDocumentViewerTabPanelSettings Width="180" />
</DxDocumentViewer>
</div>
This is my data source
[DisplayName("PatientPending")]
[HighlightedClass]
public class PatientPendingDataSource {
public PatientPendingDataSource() {
}
[HighlightedMember]
public IEnumerable<Patient> GetData() {
return new List<Patient> {
new Patient {
Id = 5
},
new Patient {
Id = 6
},
};
}
}
The datasource of this report is typeof(PatientPendingDataSource) and the datamember to "GetData" I've set a breakpoint on the GetData method but it's never reached, what am I doing wrong?

The Document Viewer in Blazor apps obtain reports from report storage. Thus, you need to locate this report into storage and specify only the ReportUrl property. When binding this report to IEnumerable<Patient> make sure that you've checked the following entries in the data source wizard and then your method should be called at runtime:
1)
2)

Related

Building ASP.NET with MVC, trying to create a filter from Dropdown list

First post here so be gentle please :)
I am creating an ASP.NET with MVC web app that shows a list of items of the same class (Laptop)
I want to create a Dropdown list in the main view below each title that will allow me to filter the results OnChange - hence the selection is empty, but the user can click and select the value in the DropDown list, and the main view items list will update immediately according to the selection.
This is how the list looks now:
Snapshot of the list
I want to implement a dropdown, but I can't seem to get the selected value from the dropdown: (The DropDownlist is populated properly, and working)
<select class="form-control" asp-items="Html.GetEnumSelectList<purpose>()"
onchange="#{Model = Model.Where(m=>m.Purpose == /*HERE SHOULD BE THE VALUE SELECTED*/)}">
<option selected="selected" value="">-Select one-</option>
</select>
And then refreshing the page... but - how do I get the selected value from inside the selection?
If it was in JavaScript I would have done:
html.document.getElementById("The id of the selection").value
but I don't want JavaScript since this is all ASP.NET
To be clear, I have 5 different dropdown lists to filter by, and they can be selected or not.
You're mixing up client-side vs. server-side code. The example below uses only MVC and a full client-server architecture. Each request requires a round-trip to the server.
You have 3 components in this scenario.
ProductsViewModel.cs
public class ProductsViewModel
{
public IList<Laptop> Laptops { get; set; }
public PurposeEnum Purpose { get; set; }
}
ProductsController.cs
public class ProductsController : Controller
{
[HttpGet]
public IActionResult Index()
{
// Retrieve all records without a filter
var unfiltered = db.Laptops.ToList();
var viewModel = new ProductsViewModel() { AvailableLaptops = unfiltered };
return View(viewModel);
}
[HttpPost]
public IActionResult Index(ProductsViewModel viewModel)
{
// Use viewModel.Purpose & viewModel.Maker to filter records from database
var filtered = db.Laptops.Where(l => l.Purpose == viewModel.Purpose).ToList();
var filteredViewModel = new ProductsViewModel()
{
AvailableLaptops = filtered,
Purpose = viewModel.Purpose
};
return filteredViewModel;
}
}
Products\Index.cshtml
#model MyNameSpace.ViewModel
using (BeginForm())
{
#Html.DropDownList(Html.GetEnumSelectList<PurposeEnum>())
foreach (var l in Model.AvailableLaptops)
{
// Loop through Model.AvailableLaptops and generate table
}
<input type="submit" value="Search" />
}
When you visit the URL /Products/Index for the first time, the GET action handler will be triggered. It will generate an unfiltered list of your products along with the dropdown list required for filtering.
When you make your selection and submit the form, the POST action handler will be triggered, and use the selected values in the Purpose and Maker properties of the view model to filter the records. The same view is generated, but with a filtered down list of products.
This is very basic code that ignores validation, error handling and security.

asp.net local database search and adding data

I have a problem with searching in my database in asp.net MVC5 app. I added to my index:
#using (Html.BeginForm())
{
<div>Wyszukaj</div>
<div>#Html.TextBox("Search")</div>
<input type="submit" value="search" />
}
And to my controller:
[HttpPost]
public ActionResult Index(string search)
{
var searching = from m in db.Books
select m;
if (!String.IsNullOrEmpty(search))
{
searching = searching.Where(s => s.Tytul.Contains(search));
}
return View(db.Books);
}
But if I type text in window and click searching, I can't see results, it is still list of my books.
I'm also unable to see the data I saved to database before running my app. When I'm trying to see my table data it's still there, but after running app, I can't see the data.
When app is running I can add the data and the data is visible in every run, but not in my table data. What am I doing wrong?

How to call async function inside Web form/ MVC Razor Asp.net? [duplicate]

Is it possible to await on tasks in Razor .cshtml views?
By default it complains that it can only be used in methods marked with async so I'm wondering if maybe there is a hidden switch somewhere that enables it?
In ASP.NET Core 2.1, you can use await in Razor views.
See https://learn.microsoft.com/en-us/aspnet/core/mvc/views/partial?view=aspnetcore-2.1
Example:
#await Html.PartialAsync("../Account/_LoginPartial.cshtml")
I've wanted something like this for a long time - a lot of the pages we write could be thrown together by a Jr Dev if they didn't have to write a bunch of queries; and, it's the same basic query boilerplate every time anyway - why should they have to write them for each Controller, when the majority of their work is to get content up? I use C# so I don't have to deal with memory management, why should an HTML coder have to deal with query details?
There is a trick you can use to sort of implicitly load data async into the View. First, you define a class that expresses what data you want. Then, at the top of each View, instantiate that class. Back in the Controller, you can lookup the View you know you're going to use, open it, then compile that class. You can then use it to go get the data the View will need, async, in the Controller the way MVC enforces. Finally, pass it off with a ViewModel to the View as MVC prescribes, and, through some trickery - you have a View that declares what data it's going to use.
Here's a StoryController. Jr Devs write stories as simple .cshtml files without having to know what a Controller, database or LINQ is:
public class StoryController : BaseController
{
[OutputCache(Duration=CacheDuration.Days1)]
// /story/(id)
public async Task<ActionResult> Id(string id = null)
{
string storyFilename = id;
// Get the View - story file
if (storyFilename == null || storyFilename.Contains('.'))
return Redirect("/"); // Disallow ../ for example
string path = App.O.AppRoot + App.HomeViews + #"story\" + storyFilename + ".cshtml";
if (!System.IO.File.Exists(path))
return Redirect("/");
return View(storyFilename);
All this does for now is go get the View file based on the URL, allowing something like WebForms (except inside MVC and using Razor). But we want to show some data - in our case, people and projects that accumulate in the database - with some standard ViewModels and Partials. Let's define how and compile that out. (Note that ConservX happens to be the core Project namespace in my case.)
public async Task<ActionResult> Id(string id = null)
{
string storyFilename = id;
// 1) Get the View - story file
if (storyFilename == null || storyFilename.Contains('.'))
return Redirect("/"); // Disallow ../ for example
string path = App.O.AppRoot + App.HomeViews + #"story\" + storyFilename + ".cshtml";
if (!System.IO.File.Exists(path))
return Redirect("/");
// 2) It exists - begin parsing it for StoryDataIds
var lines = await FileHelper.ReadLinesUntilAsync(path, line => line.Contains("#section"));
// 3) Is there a line that says "new StoryDataIds"?
int i = 0;
int l = lines.Count;
for (; i < l && !lines[i].Contains("var dataIds = new StoryDataIds"); i++)
{}
if (i == l) // No StoryDataIds defined, just pass an empty StoryViewModel
return View(storyFilename, new StoryViewModel());
// https://stackoverflow.com/questions/1361965/compile-simple-string
// https://msdn.microsoft.com/en-us/library/system.codedom.codecompileunit.aspx
// https://msdn.microsoft.com/en-us/library/system.codedom.compiler.codedomprovider(v=vs.110).aspx
string className = "__StoryData_" + storyFilename;
string code = String.Join(" ",
(new[] {
"using ConservX.Areas.Home.ViewModels.Storying;",
"public class " + className + " { public static StoryDataIds Get() {"
}).Concat(
lines.Skip(i).TakeWhile(line => !line.Contains("};"))
).Concat(
new[] { "}; return dataIds; } }" }
));
var refs = AppDomain.CurrentDomain.GetAssemblies();
var refFiles = refs.Where(a => !a.IsDynamic).Select(a => a.Location).ToArray();
var cSharp = (new Microsoft.CSharp.CSharpCodeProvider()).CreateCompiler();
var compileParams = new System.CodeDom.Compiler.CompilerParameters(refFiles);
compileParams.GenerateInMemory = true;
compileParams.GenerateExecutable = false;
var compilerResult = cSharp.CompileAssemblyFromSource(compileParams, code);
var asm = compilerResult.CompiledAssembly;
var tempType = asm.GetType(className);
var ids = (StoryDataIds)tempType.GetMethod("Get").Invoke(null, null);
using (var db... // Fetch the relevant data here
var vm = new StoryViewModel();
return View(storyFilename, vm);
}
That's the majority of the work. Now Jr Devs can just declare the data they need like so:
#using ConservX.Areas.Home.ViewModels.Storying
#model StoryViewModel
#{
var dataIds = new StoryDataIds
{
ProjectIds = new[] { 4 }
};
string title = "Story Title";
ViewBag.Title = title;
Layout = "~/Areas/Home/Views/Shared/_Main.cshtml";
}
#section css {
...
I landed on this question because I am a newbie to Razor and I wanted to display a simple "loading..." screen while my Controller Code was calculating data.
So I found this link: https://www.codeproject.com/Articles/424745/MVC-Razor-In-Progress-Icon which was helpful, but because I was a total novice at Razor, I was unable to make this work.
What finally worked for me was the following.
1) Add the "loading" div as suggested in the code project to my .cshtml file:
<div id="divLoading" style="margin: 0px; padding: 0px; position: fixed; right: 0px;
top: 0px; width: 100%; height: 100%; background-color: #666666; z-index: 30001;
opacity: .8; filter: alpha(opacity=70);display:none">
<p style="position: absolute; top: 30%; left: 45%; color: White;">
Loading, please wait...<img src="../../Content/Images/ajax-loading.gif">
</p>
</div>
2) Modify my Razor form from
<input type="submit" value="Go"/>
to
<input type="button" value="Go" onclick="JavascriptFunction()" />
3) Create the JavascriptFunction() in my .cshtml page:
<script type="text/javascript" language="javascript">
function JavascriptFunction() {
$("#divLoading").show();
$('form').submit();
}
</script>
If I understand all of the above correctly, what this does is execute the function JavascriptFunction when I press the Go button.
The JavascriptFunction does 2 things:
1) Change the view of the page by showing the previously hidden (display:none) divLoading div.
2) Submit all the forms on this page (I only have one, so it submits the form the same as if I had they type submit on the button)
After the Controller launched by the form submit is done, it loads a new view on a new page, and the initial page (and the "loading" div) is gone. Mission accomplished.
You can await calls in razor pages? I have a Blazor app and most of my methods are async:
Razor page:
<MatFAB Icon="#MatIconNames.Autorenew" Style="transform:scale(0.8); background:#333;"
OnClick="#(async () => await OnInitializedAsync())"></MatFAB>
This is a MatBlazor FloatingActionButton which calls the life time cycle event OnInitializedAsync()
C# Code:
protected override async Task OnInitializedAsync()
{
// Do something like get data when the form loads
}
No, that's not possible and you shouldn't need to do it anyway. Razor views should contain markup and at most some helper call. async/await belongs to your backend logic.
If you really need it, you can do this, it will be ugly, but it will work.
In View
#{
var foo = ViewBag.foo;
var bar = ViewBag.bar;
}
In Controller
public async Task<ActionResult> Index()
{
ViewBag.foo = await _some.getFoo();
ViewBag.bar = await _some.getBar();
return View("Index");
}
Following on MaxP's answer, it's easy to return a value from that code, despite Knagis comment:
#{
int x = DoAsyncStuffWrapper().Result;
}
#functions {
async Task<int>DoAsyncStuffWrapper()
{
await DoAsyncStuff();
}
}
I know this is an older thread, but I'll add my input just in case someone else finds it useful. I ran into this problem working with the new MongoDB driver in ASP.Net MVC - the new driver (for now), only implements async methods and returns async cursors, which can't be used in a foreach because asynccursor doesn't implement IEnumerable. The sample code typically looks like:
while(await cursor.movenextasync)
var batch=cursor.current
foreach(var item in batch)
--do stuff here--
But, this doesn't work in razor, because views are inherently not async, and await doesn't cut it.
I got it to work by changing the first line to:
while(cursor.MoveNextAsync().Result)
which returns true until the cursor hits the last entry.
Hope that helps!

Validating that a form input is not empty

I have this code for Form Submit..
<input type="submit" runat="server" id="buttonSubmit" value="Add" style="width:100px;" />
My BeginForm is like this..
<% using (Html.BeginForm("Insert", "StudentController", FormMethod.Post, new { #id = "exc-" }))
{%>
I have one textbox in my view I need to check my textbox is empty or not if it is Empty display alert box saying please Enter some value in textbox
other wise go to controler..
Please any body help me out?
thanks
You can do this many ways, but possibly the cleanest is to use Data Annotations on your ViewModel. For example -
public class MyViewModel
{
[Required]
public string MyProperty { get; set; }
}
Now in your View use
<% Html.EnableClientValidation(); %>
just before you start the form. This will cause a JavaScript object to be emitted in the markup sent to the client. The script looks like this example
<script type="text/javascript">
//<![CDATA[
if (!window.mvcClientValidationMetadata) { window.mvcClientValidationMetadata = []; }
window.mvcClientValidationMetadata.push({"Fields":[{"FieldName":"FirstName","ReplaceValidationMessageContents":true,"ValidationMessageId":"FirstName_validationMessage","ValidationRules":[{"ErrorMessage":"The First Name field is required.","ValidationParameters":{},"ValidationType":"required"}]},{"FieldName":"LastName","ReplaceValidationMessageContents":false,"ValidationMessageId":"LastName_validationMessage","ValidationRules":[{"ErrorMessage":"The Last Name field is required.","ValidationParameters":{},"ValidationType":"required"}]},{"FieldName":"EmailAddress","ReplaceValidationMessageContents":false,"ValidationMessageId":"EmailAddress_validationMessage","ValidationRules":[{"ErrorMessage":"The Email Address field is required.","ValidationParameters":{},"ValidationType":"required"}]},{"FieldName":"ZipCode","ReplaceValidationMessageContents":false,"ValidationMessageId":"ZipCode_validationMessage","ValidationRules":[{"ErrorMessage":"Zip Code must be 5 character long.","ValidationParameters":{"minimumLength":0,"maximumLength":5},"ValidationType":"stringLength"},{"ErrorMessage":"Zip Code must be five digits.","ValidationParameters":{"pattern":"\\d{5}"},"ValidationType":"regularExpression"},{"ErrorMessage":"The Zip Code field is required.","ValidationParameters":{},"ValidationType":"required"}]}],"FormId":"form0","ReplaceValidationSummary":false,"ValidationSummaryId":"valSumId"});
//]]>
</script>
This object contains validation metadata that can be used by a client side validation plugin to hook up validation on the client side. The plugin that comes with ASP.NET MVC 2 is the Microsoft AJAX validator and you will need to include these scripts in the page to use the validation (MicrosoftAjax.js, MicrosoftMVCAjax.js and MicrosoftMvcValidation.js in that order).
Alternatively, if you're more comfortable with jQuery, you can get a script in the MvcFutures source that hooks the validation into the jQuery validate plugin (this isn't a fully fledged script and is missing a few pieces, such as getting client side validation summaries). The script is MicrosoftMvcJQueryValidation.js and you can get it here
The advantage of using Data Annotations is that you get the server side validation too and your client and server side validation will validate for the expected values. Also, the Data Annotations allow you to set Error Messages and names for the field labels from the attributes (error messages and display names* can also come from resource files)
*Because MVC2 was compiled against .NET 3.5 version of Data Annotations, display name cannot be set from resource files. There is a workaround to this - DisplayName attribute from Resources?.
NOW THE EASY WAY
Just set up a submit event handler on the form
var form = document.getElementById('exc-');
var oldSubmit = form.onsubmit || function() {};
form.onsubmit = function() {
var input = document.getElementById('myinput');
if (input.value === '') {
alert('please Enter some value in textbox');
return false;
}
oldSubmit();
}
or with jQuery
$('#exc-').submit(function() {
if ($('#myinput').val() === '') {
alert('please Enter some value in textbox');
return false;
}
});

Retrieving data from Html.DropDownList() in controller (ASP MVC) | string returned?

I have the following problem:
I have a form in site/banen (currently local running webserver) which is using a SQL database. The link is made using ADO.net and is instantiated in the controller in the following way:
DBModelEntities _entities;
_entities = new DBModelEntities(); // this part is in the constructor of the controller.
Next, I use this database to fill a Html.DropDownList() in my view. This is done in two steps. At the controller side we have in the constructor:
ViewData["EducationLevels"] = this.GetAllEducationLevels();
and a helper method:
public SelectList GetAllEducationLevels()
{
List<EducationLevels> lstEducationLevels = _entities.EducationLevels.ToList();
SelectList slist = new SelectList(lstEducationLevels, "ID", "Name");
return slist;
}
In the view I have the following:
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Fields</legend>
<!-- various textfields here -->
<p>
<label for="EducationLevels">EducationLevels:</label>
<!-- <%= Html.DropDownList("EducationLevels", ViewData["EducationLevels"] as SelectList)%> -->
<%= Html.DropDownList("EducationLevels", "..select option..")%>
</p>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
Now, the form is rendered correctly when I browse to the create page. I can select etc. But when selected I have to use that value to save in my new model to upload to the database. This is where it goes wrong. I have the following code to do this in my controller:
//
// POST: /Banen/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection form)
{
// set rest of information which has to be set automatically
var vacatureToAdd = new Vacatures();
//vacatureToAdd.EducationLevels = form["EducationLevels"];
// Deserialize (Include white list!)
TryUpdateModel(vacatureToAdd);
// Validate
if (String.IsNullOrEmpty(vacatureToAdd.Title))
ModelState.AddModelError("Title", "Title is required!");
if (String.IsNullOrEmpty(vacatureToAdd.Content))
ModelState.AddModelError("Content", "Content is required!");
// Update the variables not set in the form
vacatureToAdd.CreatedAt = DateTime.Now; // Just created.
vacatureToAdd.UpdatedAt = DateTime.Now; // Just created, so also modified now.
vacatureToAdd.ViewCount = 0; // We have just created it, so no views
vacatureToAdd.ID = GetGuid(); // Generate uniqueidentifier
try
{
// TODO: Add insert logic here
_entities.AddToVacatures(vacatureToAdd);
_entities.SaveChanges();
// Return to listing page if succesful
return RedirectToAction("Index");
}
catch (Exception e)
{
return View();
}
}
#endregion
It gives the error:
alt text http://www.bastijn.nl/zooi/error_dropdown.png
I have found various topics on this but all say you can retrieve by just using:
vacatureToAdd.EducationLevels = form["EducationLevels"];
Though this returns a string for me. Since I'm new to ASP.net I think I am forgetting to tell to select the object to return and not a string. Maybe this is the selectedValue in the part where I make my SelectList but I can't figure out how to set this correctly. Of course I can also be complete on a sidetrack.
Sidenote: currently I'm thinking about having a seperate model like here.
Any help is appreciated.
You can't return an object from usual <SELECT> tag wich is rendered by Html.DropDownList() method, but only string variable could be returned. In your case ID of EducationLevels object will be send to the server. You should define and use one more custom helper method to reconstruct this object by ID.

Resources