ASP.NET MVC DevExpress XtraReport with getting parameter from View - asp.net-mvc

I want to generate a report that contains data from a database using a filter stored in a ViewData.
My question is how I will pass the ViewData value of the report as a parameter to display some data.
Controller :
var Soc = (string)TempData["Societe"];
XtraReport report = new Training.UI.Web.Reporting.Etat1();
report.DataSource = from p in db.TEntreprises
where p.EntNom == Soc
select p;
report.Parameters.Add(new DevExpress.XtraReports.Parameters.Parameter() { Name = "EntNom", Type = typeof(String), Value = Soc, Description = "NomEntreprise" });
ViewData["Report"] = report;
return PartialView("DocumentViewerPartial");
View :
#Html.DevExpress().DocumentViewer(settings =>
{
settings.Name = "documentViewer1";
settings.StylesSplitter.SidePaneWidth = 340;
settings.Report = (Training.UI.Web.Reporting.Etat1) ViewData["Report"];
settings.CallbackRouteValues = new { Controller = "Etat1", Action = "DocumentViewerPartial" };
settings.ExportRouteValues = new { Controller = "Etat1", Action = "ExportDocumentViewer" };
}).GetHtml()
And I have no data in the XtraReport

To apply the values to the report, create a string that contains the report name and the submitted values, and pass this string to the viewer’s OpenReport method.
The example below demonstrates how to do the following:
Create a page with a document viewer and button.
Create a string with the report name and a predefined parameter value and pass this string to the viewer’s OpenReport method on a button click.
Viewer.cshtml
<script type="text/javascript">
function OnClick() {
var reportName = "XtraReport1";
var paramName = "strParam";
var paramValue = "42";
var reportUrl = reportName + '?' + paramName + '=' + paramValue;
WebDocumentViewer1.OpenReport(reportUrl);
}
</script>
#Html.DevExpress().Button(settings => {
settings.Name = "dxOpenButton";
settings.Text = "Submit parameter";
settings.ClientSideEvents.Click = "OnClick";
}).GetHtml()
#Html.DevExpress().WebDocumentViewer(settings => {
settings.Name = "WebDocumentViewer1";
}).Bind("XtraReport1").GetHtml()
When you call the viewer’s OpenReport method, the reporting engine executes a report name resolution service. This service creates a report instance and returns it to the viewer. Implement this service to apply the parameter values to the report. The string argument from the OpenReport method is passed to the service’s method that returns a report instance. In this method, do the following:
Parse the string argument to extract the report name and parameter values.
Create a report instance and apply the parameter values to it. Reference each parameter by name in the report’s Parameters collection and assign the value to the parameter’s Value property.
If you want custom UI elements to be the only way to submit parameter values, hide the Parameters Panel. To do this, disable the Visible property for all report parameters. If you want users to submit parameter values from both the panel and custom UI elements, disable the report’s RequestParameters property.
Return the report instance.
When you create a Web Reporting application from the DevExpress Template Gallery, you can add the Report Storage service to the application. This service will be utilized as a report name resolution service in your application. For this, implement the service’s GetData method as follows:
CustomReportStorageWebExtenstion.CS
public override byte[] GetData(string url) {
try {
// Parse the string with the report name and parameter values.
string[] parts = url.Split('?');
string reportName = parts[0];
string parametersQueryString = parts.Length > 1 ? parts[1] : String.Empty;
// Create a report instance.
XtraReport report = null;
if (Directory.EnumerateFiles(reportDirectory).
Select(Path.GetFileNameWithoutExtension).Contains(reportName)) {
byte[] reportBytes = File.ReadAllBytes(Path.Combine(reportDirectory, reportName + FileExtension));
using (MemoryStream ms = new MemoryStream(reportBytes))
report = XtraReport.FromStream(ms);
}
if (report != null) {
// Apply the parameter values to the report.
var parameters = HttpUtility.ParseQueryString(parametersQueryString);
foreach (string parameterName in parameters.AllKeys) {
report.Parameters[parameterName].Value = Convert.ChangeType(
parameters.Get(parameterName), report.Parameters[parameterName].Type);
}
// Disable the Visible property for all report parameters
// to hide the Parameters Panel in the viewer.
foreach (var parameter in report.Parameters) {
parameter.Visible = false;
}
// If you do not hide the panel, disable the report's RequestParameters property.
// report.RequestParameters = false;
using (MemoryStream ms = new MemoryStream()) {
report.SaveLayoutToXml(ms);
return ms.ToArray();
}
}
} catch (Exception) {
// ...
}
To apply parameter values from a URL query string to a report, implement the viewer’s action method as follows:
Create a report instance and apply the parameter values to it. Reference each parameter by name in the report’s Parameters collection and assign the value to the parameter’s Value property.
If you want a URL’s query string to be the only way to submit parameter values, hide the Parameters Panel. To do this, disable the Visible property for all report parameters. If you want users to submit parameter values from both the panel and a URL’s query string, disable the report’s RequestParameters property.
Return a report view.
The example below demonstrates how to implement the viewer’s action method to apply the parameter value from the query string of the following URL: https://localhost:5001/Home/Viewer?intParam=42.
HomeController.cs
public ActionResult Viewer(int? intParam) {
var report = new XtraReport1();
report.Parameters["intParam"].Value = intParam;
report.Parameters["intParam"].Visible = false;
return View(report);
}
enter image description here

Related

html.dropdownlistfor bind selected value to one column, set another column to the selected Text

I'm fairly new to mvc and razor views.
I have a DropDownListFor that successfully is populated with a list of values and text from a data table.
I also am successfully binding the selected value to a data column in my data model.
However, the database that I'm working with is not normalized and I have need to taking the Text from the selected item, and binding that to another field in my data model.
How hard is it to do this?
You have several options:
1. Call the database to get text after submit
public ActionResult Submit(int dropDownListId)
{
var text = string.Empty;
var dataItem = this._dbContext.SomeTableData.SingleOrDefault(m => m.Id == dropDownListId);
if (dataItem != null)
{
text = dataItem.Title;
}
// continue
}
2. Adjust the drop down list value and parse the value in controller/business layer:
If you're using the default DropDownListFor HtmlHelper your data source is type of IEnumerable<SelectListItem> so while you're building your Model class you're going to pass it to the view, do something like this:
//get data from database
var dataSource = this_dbContext.SomeTableData.Select(m => new SelectListItem()
{
Value = string.Format("{0}|{1}", m.Id, m.Title),
Text = m.Title
}
And after you submit data parse the value:
public ActionResult Submit(string dropDownListValue) {
string[] values = dropDownListValue.Split('|');
// values[0] = value
// values[1] = text
}
3. Add hidden field to the view and use JavaScript to store the text
$('#dropDownListId').on('change', function () {
var text = $(this).find('option:selected').text();
$('#dropDownListText').val(text); // hidden field
});
and collect the value after submit:
public ActionResult Submit(int dropDownListId, string dropDownListText)
{
//logic
}

MvcSiteMapProvider bug with pagination

It's continue ASP.NET MVC incorect generation url when using pagination, but there I found how fix it. How fix that when using #Html.MvcSiteMap().SiteMapPath() I can't understand.
Problem in that when in actions ShowForum or ShowTopic and when I using pagination some forum or topic. In #Html.MvcSiteMap().SiteMapPath() I get url at parent page with number of page
UPDATE
For route configuration I'm using route attribute
[HttpGet]
[Route("{forumName}", Name = "showForum", Order = 6)]
[Route("{forumName}/Page/{page}", Order = 5)]
[OutputCache(Duration = 30, VaryByParam = "forumName;page", Location = OutputCacheLocation.ServerAndClient)]
public async Task<ActionResult> ShowForum(string forumName, int page = 1)
[HttpGet]
[RefreshDetectFilter]
[Block(VisibleBlock = false)]
[Route("{forum}/{topicName}", Name = "showTopic", Order = 8)]
[Route("{forum}/{topicName}/Page/{page}", Order = 7)]
[OutputCache(Duration = 30, VaryByParam = "topicName;page", Location = OutputCacheLocation.ServerAndClient)]
public async Task<ActionResult> ShowTopic(string forum, string topicName, int page = 1)
My ForumDynamicNodeProvider
public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
{
var rootTitle = ManagerLocalization.Get("Forums", "FORUMS");
var pageParameter = new List<string> { "page" };
var url = "~/Forums";
var attr = new Dictionary<string, object> { { "Controller", "Forums" } };
var nodes = new List<DynamicNode>
{
new DynamicNode
{
Key = "forum_home",
Title = rootTitle,
Url = url,
Attributes = attr
}
};
var forums = this._forumsService.GetAllForumsForMap();
var topics = this._forumsService.GetAllTopicsForMap();
foreach (var forum in forums)
{
var forumRouteValue = new Dictionary<string, object> { { "forumName", forum.NameTranslit } };
nodes.Add(new DynamicNode
{
ParentKey = forum.ForumId != -1 ? $"forum_{forum.ForumId}" : "forum_home",
Key = $"forum_{forum.Id}",
Title = forum.Name,
PreservedRouteParameters = pageParameter,
Controller = "Forums",
Action = "ShowForum",
RouteValues = forumRouteValue,
});
var forumTopics = topics.Where(item => item.ForumId == forum.Id);
foreach (var topic in forumTopics)
{
var topicRouteValue = new Dictionary<string, object> { { "forum", forum.NameTranslit }, { "topicName", topic.TitleTranslite } };
nodes.Add(new DynamicNode
{
ParentKey = $"forum_{forum.Id}",
Key = $"topic_{topic.Id}",
Title = topic.Title,
PreservedRouteParameters = pageParameter,
Controller = "Forums",
Action = "ShowTopic",
RouteValues = topicRouteValue,
});
}
}
return nodes;
}
The problem is that you are using the same route key name {page} in two different places in the same node ancestry in combination with PreservedRouteParameters. PreservedRouteParameters gets its data from the current request. So, it is important that a route key have the same meaning in each request in the same node ancestry. For it to work correctly with PreservedRouteParamters, you need to do three things:
Use a different route key for each separate page parameter (for example, {forumPage} and {page}).
Ensure the ancestor page parameter is passed to the request of its descendants, so when building the URL to an ancestor node the value is in the current request. The simplest way is to build the URL with the page information of all ancestors ({forumName}/Page/{forumPage}/{topicName}/Page/{page}).
Any route keys that have the same meaning between nodes should stay the same ({forumName} in both routes).
Then you need to add the parameters when building the URL of the child node. You must build the URL manually within your application because the request will not have all of the parameters unless you do.
#Html.ActionLink("TheTopicName", "ShowTopic", "Forums",
new { forumName = 1, forumPage = 2, topicName = "foo", page = 1 }, null)
The reason you must supply all of the data in the child node request is because the ancestor node needs it to build its URL. It pulls this information from the request, so it must be present in the request for it to function. MvcSiteMapProvider has no way of knowing what the current page number of the ancestor node is unless it is provided in the request by a URL that is built outside of your menu.
See the MvcSiteMapProvider-Forcing-A-Match-2-Levels project in the code download for How to Make MvcSiteMapProvider Remember a User's Position for a similar configuration and the solution. In that case, it is using productId instead of forumPage as the parameter that is preserved on the descendant nodes so you can navigate back to the parent product.
Note that you could use a similar configuration (with PreservedRouteParameters and SiteMapTitleAttribute) for your entire forum rather than using a dynamic node provider. However, in that case I would suggest you disable the /sitemap.xml endpoint and roll your own.
I found how this fix, thank you to NightOwl888. I'm not the first time understood what should to do.
First I removed initialization PreservedRouteParameters in ForumDynamicNodeProvider
Second I added in action
if (forumPage > 1)
{
var node = SiteMaps.Current.FindSiteMapNodeFromKey(forumName);
if (node != null)
{
node.RouteValues["forumPage"] = forumPage;
}
}
Also I need change generation tree in ForumDynamicNodeProvider because SiteMaps.Current doesn't work in async

How to create custom function on OData RESTier

I'm referring to http://odata.github.io/RESTier/#03-01-Operations on how to create a custom method that takes in input and return a list of object.
Here's my custom method
[HttpGet]
[ODataRoute("Locations/PointLoc.Data.GetLocationsByMarketId()")]
public IHttpActionResult GetLocationsByMarketId()
{
var database = new Database();
var locations = database.Locations.GetAllLocationsByMarket(1);
return Ok(locations);
}
And here's how I set it in my DbDomain
protected EdmModel OnModelExtending(EdmModel model)
{
var ns = model.DeclaredNamespaces.First();
var location = model.FindDeclaredType(ns + "." + "Location");
var locations = EdmCoreModel.GetCollection(location.GetEdmTypeReference(isNullable: false));
var getLocationsWithMarketId = new EdmFunction(ns, "GetLocationsWithMarketId", locations, true, null, false);
getLocationsWithMarketId.AddParameter("bindingParameter", locations);
model.AddElement(getLocationsWithMarketId);
return model;
}
Can't get it to work. Keep getting OData Uri error like
'Locations/PointLoc.Data.GetLocationsByMarketId()' on the action 'GetLocationsByMarketId' in controller 'PointLoc' is not a valid OData path template. The request URI is not valid. Since the segment 'Locations' refers to a collection, this must be the last segment in the request URI or it must be followed by an function or action that can be bound to it otherwise all intermediate segments must refer to a single resource.
Wanted to access the Odata via "/Locations/GetLocationsByMarketId". How to do it?

How to populate Selectlist using stored procedure

In my MVC application I am trying to retrieve data using a stored procedure, then display it in a dropdown.
Here is My controller action
public ActionResult Register(string id )
{
RegistrationModel Student = new RegistrationModel();
using (var db = new StudentEntities())
{
var SportResultList = GetListOfSport();
var SportSelectList = new SelectList(SportResultList);
ViewBag.SportList = SportSelectList;
return View(Student);
}
Here is the Method to get the list using the stored procedure
public static List<GetSportsResult> GetListOfSport()
{
using (var db = new StudentEntities())
{
ObjectResult<GetSportsResult> SportResults = db.GetSportsByStudentIdAndSeason(11111, 1);
List<GetSportsResult> results = SportResults.ToList();
return results;
}
}
The stored procedure returns a complex type called GetSportsResults but I don't now how to access its fields.
Currently this code will display the GetSportsResults 20 times which is the right amount of records I should be getting
In the constructor for SelectList you can specify which fields are to be used for the text and for the value. This is done by passing string values to the constructor.
For example, if your GetSportsResult object has a .ID property as its identifier and a .Name property as its display value, then your code would look like this:
var SportResultList = GetListOfSport();
var SportSelectList = new SelectList(SportResultList, "ID", "Name");
ViewBag.SportList = SportSelectList;
This would indicate to the SelectList object that GetSportsResult.ID should be the value for each item in the list, and GetSportsResult.Name should be the displayed text for each item in the list.
Without specifying these fields, currently the object tries to make a "best guess" of what to display. It's probably doing this by calling .ToString() on each object by default. And the default behavior of .ToString() on a non-primative type is to display the name of the type itself, which is why you're seeing the string "GetSportsResult" for each item.

save form values through script file in umbraco

hello i want to save the value of umbraco form in database for this i have made script file and in this script file i have created function to save data and called this function in same script file and this script file is used in macro and i have called this macro in template of my page but it is not working will this approach is proper or i have to something else my basic aim is to save data in database without creating my usercontrol
code is
#functions
{
public void AddToCart()
{
string con = System.Configuration.ConfigurationManager.AppSettings["umbracoDbDSN"].ToString();
SqlConnection OnCon = new SqlConnection(System.Configuration.ConfigurationManager.AppSettings["umbracoDbDSN"].ToString());
ItemsDataContext db = new ItemsDataContext(con);
var request = HttpContext.Current.Request;
string itemcode= request.Form["ItemCode"].ToString();
string itemname = request.Form["ItemName"].ToString();
string itemcategory = Request.Form["ItemCategory"].ToString();
string userid = "Pallavi";
db.sp_AddItems(userid, itemcode, itemcategory, itemname, 0);
HttpContext.Current.Session["UserId"] = "Pallavi";
}
}
#if (!IsPost)
{
AddToCart();
}
and called this macro on template
<umbraco:Macro Alias="Uc_Cart" runat="server"></umbraco:Macro>
You approach is wrong. You must use the methods that Umbraco provides in their API and do not try to write data into the database directly.
Try this code to create an new document from Razor code:
#using umbraco.BusinessLogic;
#using umbraco.cms.businesslogic.web;
#{
DocumentType dt = DocumentType.GetByAlias("Textpage");
User author = umbraco.BusinessLogic.User.GetUser(0);
Document doc = Document.MakeNew("My new document", dt, author, parentID);
}
The example above is for Umbraco 4.x. If you're using Umbraco v6.x you could also use the new API methods:
#{
// get an instance of the contentService
var contentService = ApplicationContext.Services.ContentService;
// create new content, the last param is the userId and is optional [default = 0]
IContent newContent = contentService.CreateContent("My new document", parentID, "Textpage", 0);
// set property values
newContent.SetValue("propertyAlias", "Value");
// save (or save and publish)
contentService.Save(newContent);
}

Resources