Asp.net Generating Pages from DB - c#

It is possible to generate permanent pages with asp.net with stuff stored on database?
For example a few locations/types and i want to do something like the single example:
Location: New York
Type: Car
Generated Permanent Page With information:
Cars in New York
Generated link:
mywebsite.com/cars/newyork
At the moment i've done a search filter displays the results based on Selected Location and Selected type.
Hope you can give me some tips about this.

One approach is to save HTML template in db and then use string.Format to insert values
e.g like that
string name = "test";
int age = 167;
string test = "{0} format {1}";
string[] args = new string[] { name, age.ToString() };
Console.WriteLine(string.Format(test, args));
prints: test format 167
Then you return View with string that is your html with inserted values and then you "display" (allow browser to render) it using
#model string
#Html.Raw(#Model)
https://learn.microsoft.com/en-us/dotnet/api/system.web.mvc.htmlhelper.raw?view=aspnet-mvc-5.2
But be careful, because it may be very dangerous if user is able to provide/manipulate those values. Read about XSS attack.

Related

Subsetting data coming from database

I have a model which collects data in my ASP.NET MVC app:
namespace myapp.Models
{
[Table("mytable")]
public partial class mytbl
{
// column specifications
}
}
but this model takes all rows of the selected table. I want to add some filter rules. In an SQL query it's look so;
SELECT *
FROM mytable
WHERE mycol = 2 OR mycol = 3
in above example I typed 2 and 3 by hand but I have a text file toshow.txt (located at wwwroot) the contents of the toshow.txt file is;
2
3
How can I subset the data according to the text file ?
I'm not super familiar with ASP.NET MVC app development. Sorry if my question doesn't make sense.
Thanks in advance.
You'll need to
read the file
convert strings read from the file to int values
filter the data in the database
The below should at least get you started:
// get filename and read the file
string fileName = Path.Combine(_env.WebRootPath, "toshow.txt");
string[] lines = File.ReadAllLines(fileName);
// parse values in file to List<int>
List<int> filter = lines.Select(line => int.Parse(line)).ToList();
// could also be written lines.Select(int.Parse)
// filter your DB
var filteredResult = _context.MyTable.Where(x => filter.Contains(x.MyCol));
Where _env is an IWebHostingEnvironment and WebRootPath maps to the wwwroot directory. You may need to use ContentRootPath instead if you're using IHostingEnvironment. More details can be found in Static files in Asp.Net Core.
The above will filter MyCol on the values in the file.
You'll also need to perform your own error checking and validation if, for example, the file doesn't contain values which are convertible to ints.

How to get particular infomation stored in list

I am using a existing web service which does a postcode search its then stored In a list box the values: "ID", "Text", "Highlight", "Cursor", "Description", "Next". I need to try and access a particular string value which is the ID & Next param and use it for validation later on. When I click on the list box I want the particular data to be taken stored then access the two pieces of information I need. How do I access the information on a particular row of the list box and use that later on?
try
{
int myMaxResultValue = (int)nud_MaxResults.Value;
int myMaxSuggestValue = (int)nud_MaxSuggestions.Value;
findResults = objBvSoapClient.CapturePlus_Interactive_Find_v2_10("Dak4-KZ62-AAdd87-X55", txt_Search.Text, txt_LastId.Text, cb_SearchFor.Text, text_Country.Text, text_LanguagePreference.Text, myMaxResultValue, myMaxSuggestValue);
if (txt_Search.Text.Length <= 2)// if less than two letters are entered nothing is displayed on the list.
{
ls_Output.Items.Clear();// Clear LstBox
ls_Output.Items.Add(String.Format(allDetails, "ID", "Text", "Highlight", "Cursor", "Description", "Next"));
MessageBox.Show("Please enter more than 2 Chars!!");
}
else if (txt_Search.Text.Length >= 3)// if greater than or equal to 3 letters in the search box continue search.
{
// Get Results and store in given array.
foreach (var items in findResults)
{ //Loop through our collection of found results and change resulting value.
ls_Output.Items.Add(String.Format(allDetails, items.Id, items.Text.ToString(), items.Highlight, items.Cursor, items.Description, items.Next));
}
}
}
As a side note your string.Format missing the variables in the string. It should be more like this
int id = 30;
string text = "Hello";
string.Format("This is the ID {0}. Here is some text {1}.", id, text);
The output will be "This is the ID 30. Here is some text Hello.".
To answer your question, you'll have to parse it to pull out the parts you want. You could use regex.split to do this. For example, if it's delimited on space you could do something like this
string[] data = Regex.Split(operation, #"\s+");
Then you can access it like this
string required = data[3];

Aspose.Words - MailMerge images

I am trying to loop through a Dataset, creating a page per item using Aspose.Words Mail-Merge functionality. The below code is looping through a Dataset - and passing some values to the Mail-Merge Execute function.
var blankDocument = new Document();
var pageDocument = new Document(sFilename);
...
foreach (DataRow row in ds.Tables[0].Rows){
var sBarCode = row["BarCode"].ToString();
var imageFilePath = HttpContext.Current.Server.MapPath("\\_temp\\") + sBarCode + ".png";
var tempDoc = (Document)pageDocument.Clone(true);
var fieldNames = new string[] { "Test", "Barcode" };
var fieldData = new object[] { imageFilePath, imageFilePath };
tempDoc.MailMerge.Execute(fieldNames, fieldData);
blankDocument.AppendDocument(tempDoc, ImportFormatMode.KeepSourceFormatting);
}
var stream = new MemoryStream();
blankDocument.Save(stream, SaveFormat.Docx);
// I then output this stream using headers,
// to cause the browser to download the document.
The mail merge item { MERGEFIELD Test } gets the correct data from the Dataset. However the actual image displays page 1's image on all pages using:
{ INCLUDEPICTURE "{MERGEFIELD Barcode }" \* MERGEFORMAT \d }
Say this is my data for the "Barcode" field:
c:\img1.png
c:\img2.png
c:\img3.png
Page one of this document, displays c:\img1.png in text for the "Test" field. And the image that is show, is img1.png.
However Page 2 shows c:\img2.png as the text, but displays img1.png as the actual image.
Does anyone have any insight on this?
Edit: It seems as this is more of a Word issue. When I toggle between Alt+F9 modes inside Word, the image actually displays c:\img1.png as the source. So that would be why it is being displayed on every page.
I've simplified it to:
{ INCLUDEPICTURE "{MERGEFIELD Barcode }" \d }
Also, added test data for this field inside Word's Mailings Recipient List. When I preview, it doesn't pull in the data, changing the image. So, this is the root problem.
I know this is old question. But still I would like to answer it.
Using Aspose.Words it is very easy to insert images upon executing mail merge. To achieve this you should simply use mergefield with a special name, like Image:MyImageFieldName.
https://docs.aspose.com/words/net/insert-checkboxes-html-or-images-during-mail-merge/#how-to-insert-images-from-a-database
Also, it is not required to loop through rows in your dataset and execute mail merge for each row. Simply pass whole data into MailMerge.Execute method and Aspose.Words will duplicate template for each record in the data.
Here is a simple example of such template
After executing mail merge using the following code:
// Create dummy data.
DataTable dt = new DataTable();
dt.Columns.Add("FirstName");
dt.Columns.Add("LastName");
dt.Columns.Add("MyImage");
dt.Rows.Add("John", "Smith", #"C:\Temp\1.png");
dt.Rows.Add("Jane", "Smith", #"C:\Temp\2.png");
// Open template, execute mail merge and save the result.
Document doc = new Document(#"C:\Temp\in.docx");
doc.MailMerge.Execute(dt);
doc.Save(#"C:\Temp\out.docx");
The result will look like the following:
Disclosure: I work at Aspose.Words team.
If this was Word doing the output, (not sure about Aspose), there would be two possible problems here.
INCLUDEPICTURE expects backslashes to be doubled up, e.g. "c\\img2.png", or (somewhat less reliable) to use forward slashes, or Mac ":" separators on that platform. It may be OK if the data comes in via a field result as you are doing here, though.
INCLUDEPICTURE results have not updated automatically "by design" since Microsoft modified a bunch of field behaviors for security reasons about 10 years ago. If you are merging to an output document, you can probably work around that by using the following nested fields:
{ INCLUDEPICTURE { IF TRUE "{ MERGEFIELD Barcode }" } }
or to remove the fields in the result document,
{ IF { INCLUDEPICTURE { IF TRUE "{ MERGEFIELD Barcode }" } } {
INCLUDEPICTURE { IF TRUE "{ MERGEFIELD Barcode }" } } }
All the { } need to be inserted with Ctrl+F9 in the usual way.
(Don't ask me where this use of "TRUE" is documented - as far as I know, it is not.)

how to send email wth email template c#

suppose i need to send mail to customer with customer detail and his order detail.
i have template html data in a html file.customer data is there and as well as order detail is also there in same html template file. my html look like
<html>
<body>
Hi {FirstName} {LastName},
Here are your orders:
{foreach Orders}
Order ID {OrderID} Quantity : {Qty} <strong>{Price}</strong>.
{end}
</body>
</html>
now i want to fill up all sample keyword surrounded with {} with actual value and also iterate and fill up orders.
i search google and found that microsoft provide a class called MailDefinition
by which we can generate mail body dynamically. i got a sample code also like
MailDefinition md = new MailDefinition();
md.From = "test#domain.com";
md.IsBodyHtml = true;
md.Subject = "Test of MailDefinition";
ListDictionary replacements = new ListDictionary();
replacements.Add("<%Name%>", "Martin");
replacements.Add("<%Country%>", "Denmark");
string body = "
Hello <%Name%> You're from <%Country%>.";
MailMessage msg = md.CreateMailMessage("you#anywhere.com", replacements, body, new System.Web.UI.Control());
by the above code we can replace pseudo value with actual value but i don't know how iterate in Orders detail and populate orders data.
so if it is possible using MailDefinition class then please guide me with code that how can i iterate in loop and generate body for orders detail.
As an alternative to MailDefinition, have a look at RazorEngine https://github.com/Antaris/RazorEngine.
RazorEngine is a simplified templating framework built around
Microsoft's new Razor parsing engine, used in both ASP.NET MVC3 and
Web Pages. RazorEngine provides a wrapper and additional services
built around the parsing engine to allow the parsing technology to
be used in other project types.
It lets you use razor templates outside of ASP.NET MVC and then write something like this (not tested):
string template =
#"<html>
<body>
Hi #Model.FirstName #Model.LastName,
Here are your orders:
#foreach(var order in Model.Orders) {
Order ID #order.Id Quantity : #order.Qty <strong>#order.Price</strong>.
}
</body>
</html>";
var model = new OrderModel {
FirstName = "Martin",
LastName = "Whatever",
Orders = new [] {
new Order { Id = 1, Qty = 5, Price = 29.99 },
new Order { Id = 2, Qty = 1, Price = 9.99 }
}
};
string mailBody = Razor.Parse(template, model);
You can't do such "complicated" logic with the default replacement stuff (the placeholder handling is made to be used for simple variables only, e.g. names or values).
You'll have to do the parsing yourself. Depending on the complexity (e.g. loops withing loops), this can get a bit tricky.
If you don't want or need such things, it's more trivial. E.g. use the regular expression \{foreach (.*?)\}(.*?)\{end\} to find such loops, then parse the contents/matched groups the way you need. Once that part is done, you could replace other values or use the default replacement feature.
Only downside with this approach is the fact that you'll have to recreate the mail for each recipient (i.e. you can't mass mail using MailDefinition).

Method to find / eliminate repetitive strings

I am trying to find a solution, in eliminating repetitive string names, say for ex.,
in a literal field, i am populating names of the contributor of certain article's history version, and so, if "ron" has contributed to the versioning of an article 3 times, the name "ron" gets added to this literal control, and outputs "ron" 3 times.
I am trying to find, if a name is repeating twice, i should be able to populate it only one time. How can i achieve this ?
I would suggest you to use dictionary whose keys will be the author name (or the field which you don't want to be repetitive) and values will be the lists of contributors. For example,
Dictionary<string, List<Contributor>> contributors
= new Dictionary<string, List<Contributor>>();
Contributor contributor = new Contributor("ron", /*other values*/);
if ( !contributors.ContainsKey(contributor.Name) )
contributors.Add(contributor.Name,new List<Contributor>());
contributors[contributor.Name].Add(contributor);
Depending on your setup, I'd either use a StringCollection and just check if the name exists prior to insertion or just add all the names to a List and call Distinct() (extension method in System.Linq). So either:
StringCollection Names=new StringCollection();
if(!Names.Contains(Name))
Names.Add(Name);
As CharithJ suggests, or:
List<string> Names=new List<string>();
Names.Add(Name);
...
foreach(string Name in Names.Distinct())
{
...
}
Either would work well enough.
Use C#s .Contains() function to check if the name has already been added to the string
Create a model of what you want to achieve (it's like a view model) that drives the rendering of your "report". Then, the model can control this requirement of "only output each name once". Pseudo-code follows:
var ron = new Author("ron");
var ronnie = new Author("ronnie");
var report = new HistoryReport();
report.AddVersion(1, ron);
report.AddVersion(2, ron);
report.AddVersion(3, ronnie);
string renderedReport = report.Render();
// output e.g.:
// Versions 1 and 2 by ron; Version 3 by ronnie
Then you use that ouput to populate your literal control.
If you use simple string substitution, you'll mix up ron with ronnie.
StringCollection authors= new StringCollection();
if (!authors.Contains("Ron"))
{
authors.Add("Ron");
}

Categories