پیادهسازی TenantScoped با استفاده از IoC Container توکار
نظرات اشتراکها
public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API configuration and services // Web API routes config.MapHttpAttributeRoutes(); } }
public class VideoStream { private readonly string _filename; private long _contentLength; public long FileLength { get { return _contentLength; } } public VideoStream(string videoPath) { _filename = videoPath; using (var video = File.Open(_filename, FileMode.Open, FileAccess.Read, FileShare.Read)) { _contentLength = video.Length; } } public async void WriteToStream(Stream outputStream, HttpContent content, TransportContext context) { try { var buffer = new byte[65536]; using (var video = File.Open(_filename, FileMode.Open, FileAccess.Read, FileShare.Read)) { var length = (int)video.Length; var bytesRead = 1; while (length > 0 && bytesRead > 0) { bytesRead = video.Read(buffer, 0, Math.Min(length, buffer.Length)); await outputStream.WriteAsync(buffer, 0, bytesRead); length -= bytesRead; } } } catch (HttpException) { return; } finally { outputStream.Close(); } } }
while (length > 0 && bytesRead > 0) { bytesRead = video.Read(buffer, 0, Math.Min(length, buffer.Length)); await outputStream.WriteAsync(buffer, 0, bytesRead); length -= bytesRead; }
public class VideoController : ApiController { [Route("api/video/{ext}/{fileName}")] public HttpResponseMessage Get(string ext, string fileName) { string videoPath = HostingEnvironment.MapPath(string.Format("~/Videos/{0}.{1}", fileName, ext)); if (File.Exists(videoPath)) { FileInfo fi = new FileInfo(videoPath); var video = new VideoStream(videoPath); var response = Request.CreateResponse(); response.Content = new PushStreamContent((Action<Stream, HttpContent, TransportContext>)video.WriteToStream, new MediaTypeHeaderValue("video/" + ext)); response.Content.Headers.Add("Content-Disposition", "attachment;filename=" + fi.Name.Replace(" ", "")); response.Content.Headers.Add("Content-Length", video.FileLength.ToString()); return response; } else { return Request.CreateResponse(HttpStatusCode.NotFound); } } }
[Route("api/video/{ext}/{fileName}")]
api/video/mp4/sample
string videoPath = HostingEnvironment.MapPath(string.Format("~/Videos/{0}.{1}", fileName, ext));
var video = new VideoStream(videoPath);
var response = Request.CreateResponse(); response.Content = new PushStreamContent((Action<Stream, HttpContent, TransportContext>)video.WriteToStream, new MediaTypeHeaderValue("video/" + ext));
response.Content.Headers.Add("Content-Disposition", "attachment;filename=" + fileName); response.Content.Headers.Add("Content-Length", video.FileLength.ToString());
if(File.Exists(videoPath)) { // removed for bravity } else { return Request.CreateResponse(HttpStatusCode.NotFound); }
public class HomeController : Controller { // GET: Home public ActionResult Index() { return View(); } }
<div> <div> <video width="480" height="270" controls="controls" preload="auto"> <source src="/api/video/mp4/sample" type="video/mp4" /> Your browser does not support the video tag. </video> </div> </div>
import { connect } from "react-redux"; import Posts from "../components/Posts"; const mapStateToProps = state => { console.log("PostsContainer->mapStateToProps", state); return { ...state.postsReducer }; }; export default connect(mapStateToProps)(Posts);
const Posts = ({ posts, loading, error }) => { return ( // ...
import { useSelector } from "react-redux"; // ... const HooksPosts = () => { const { posts, loading, error } = useSelector(state => state.postsReducer); return ( // ...
import PostsContainer from "./containers/Posts"; function App() { return ( <main className="container"> <PostsContainer /> </main> ); }
import HooksPosts from "./components/HooksPosts"; function App() { return ( <main className="container"> <HooksPosts /> </main> ); }
import { connect } from "react-redux"; import { fetchPostsAsync } from "../actions"; import FetchPosts from "../components/FetchPosts"; const mapDispatchToProps = { fetchPostsAsync }; export default connect(null, mapDispatchToProps)(FetchPosts);
const FetchPosts = ({ fetchPostsAsync }) => {
import React from "react"; import { useDispatch } from "react-redux"; import { fetchPostsAsync } from "../actions"; const HooksFetchPosts = () => { const dispatch = useDispatch(); return ( <section className="card mt-5"> <div className="card-header text-center"> <button className="btn btn-primary" onClick={() => dispatch(fetchPostsAsync())} > Fetch Posts </button> </div> </section> ); }; export default HooksFetchPosts;
import HooksFetchPosts from "./components/HooksFetchPosts"; import HooksPosts from "./components/HooksPosts"; // ... function App() { return ( <main className="container"> <HooksFetchPosts /> <HooksPosts /> </main> ); }
import { connect } from "react-redux"; import { decrementValue, incrementValue } from "../actions"; import Counter from "../components/counter"; const mapStateToProps = (state, ownProps) => { console.log("CounterContainer->mapStateToProps", { state, ownProps }); return { count: state.counterReducer.count }; }; const mapDispatchToProps = { incrementValue, decrementValue }; export default connect(mapStateToProps, mapDispatchToProps)(Counter);
class Counter extends Component { render() { console.log("Counter->props", this.props); const { //counterReducer: { count }, count, incrementValue, decrementValue } = this.props;
import React from "react"; import { useDispatch, useSelector } from "react-redux"; import { decrementValue, incrementValue } from "../actions"; const HooksCounter = ({ prop1 }) => { const { count } = useSelector(state => { console.log("HooksCounter->useSelector", { state, prop1 }); return { count: state.counterReducer.count }; }); const dispatch = useDispatch(); return ( // ...
import HooksCounter from "./components/HooksCounter"; //... function App() { const prop1 = 123; return ( <main className="container"> <HooksCounter prop1={prop1} /> </main> ); }
import React from "react"; import { useDispatch, useSelector } from "react-redux"; import { decrementValue, incrementValue } from "../actions"; const HooksCounter = ({ prop1 }) => { const { count } = useSelector(state => { console.log("HooksCounter->useSelector", { state, prop1 }); return { count: state.counterReducer.count }; }); const dispatch = useDispatch(); return ( <section className="card mt-5"> <div className="card-body text-center"> <span className="badge m-2 badge-primary">{count}</span> </div> <div className="card-footer"> <div className="d-flex justify-content-center align-items-center"> <button className="btn btn-secondary btn-sm" onClick={() => dispatch(incrementValue())} > + </button> <button className="btn btn-secondary btn-sm m-2" onClick={() => dispatch(decrementValue())} > - </button> <button className="btn btn-danger btn-sm">Reset</button> </div> </div> </section> ); }; export default HooksCounter;
import React from "react"; import { shallowEqual, useSelector } from "react-redux"; import Post from "./Post"; const HooksPosts = () => { const { posts, loading, error } = useSelector( state => state.postsReducer, shallowEqual ); console.log("render HooksPosts"); return ( // ...
- همانطور که در تصویر مشاهده میکنید؛ آدرس پروژهی لوکال ما به شکل زیر میباشد:
http://localhost:51095/Home/Index
ngrok http [port] -host-header="localhost:[port]"
http://127.0.0.1:4040